Skip to content

Commit

Permalink
Merge branch 'feature/pages_api'
Browse files Browse the repository at this point in the history
  • Loading branch information
JustinAiken committed Jan 22, 2018
2 parents 2515c24 + 9486e7e commit 5694e04
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 70 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Next

- Fully automated! Use new gitlab API for the last step

# 0.1.0

- #6 - Added option to get secret gitlab token from env var
Expand Down
30 changes: 4 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@

![img](doc/image.png)

This plugin automagically does 90% of the letsencrypt process for your gitlab-hosted jekyll blog.
This plugin automagically does the entire the letsencrypt process for your gitlab-hosted jekyll blog!

- *(automatic)* It registers your email to the letsencrypt server
- *(automatic)* It generates a challenge file, and commits it directly via the gitlab API
- *(automatic)* It sleeps until the challenge file is live on the internet
- *(automatic)* It asks letsencrypt to verify it
- *(automatic)* It spits out the certificate chain and private key
- *(manual)* You have to go to the URL provided and manually copy/paste them
- This step must be manual since there is no API through Gitlab for this step
- *(automatic)* It updates the gitlab pages domain settings to use the certificate

## Usage

Expand Down Expand Up @@ -93,29 +92,8 @@ Requesting verification...
Challenge status = valid
Challenge is valid!
Certificate retrieved!
Go to https://gitlab.com/gitlab_user/gitlab_repo/pages
- If you already have an existing entry for example.com, remove it
- Then click + New Domain and enter the following:
Domain: example.com
Certificate (PEM):
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Key (PEM):
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
... hit save, wait a bit, and your new SSL will be live!
Updating domain example.com pages setting with new certificates..
Success!
```

### Alternative token usage
Expand Down
2 changes: 1 addition & 1 deletion jekyll-gitlab-letsencrypt.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "coveralls"

spec.add_dependency "activesupport", ">= 3.0.0"
spec.add_dependency "acme-client", "~> 0.5.0"
spec.add_dependency "acme-client", "~> 0.6"
end
2 changes: 1 addition & 1 deletion lib/jekyll/gitlab/letsencrypt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
require 'jekyll/gitlab/letsencrypt/configuration'
require 'jekyll/gitlab/letsencrypt/acme'
require 'jekyll/gitlab/letsencrypt/process'
require 'jekyll/gitlab/letsencrypt/committer'
require 'jekyll/gitlab/letsencrypt/gitlab_client'

module Jekyll
module Gitlab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@
module Jekyll
module Gitlab
module Letsencrypt
class Commiter
class GitlabClient

attr_accessor :content

delegate :filename, :personal_access_token, :gitlab_repo, :branch, to: Configuration
delegate :filename, :personal_access_token, :gitlab_repo, :branch, :domain, to: Configuration

def initialize(content)
def commit!(content)
@content = content
end

def commit!
create_branch! unless branch_exists?
commit_file!
end

def update_certificate!(certificate, key)
Jekyll.logger.info "Updating domain #{domain} pages setting with new certificates.."
response = connection.put do |req|
req.url "projects/#{repo_id}/pages/domains/#{domain}"
req.body = {
certificate: certificate,
key: key
}.to_json
end
response.success?
end

def create_branch!
Jekyll.logger.info "Creating branch #{branch}.."
connection.post do |req|
Expand All @@ -31,7 +40,7 @@ def create_branch!

def commit_file!
Jekyll.logger.info "Commiting challenge file as #{filename}"
connection.run_request(request_method, nil, nil, nil) do |req|
connection.run_request(request_method_for_commit, nil, nil, nil) do |req|
req.url "projects/#{repo_id}/repository/files"
req.body = {
file_path: filename,
Expand All @@ -50,7 +59,7 @@ def branch_exists?
JSON.parse(response.body).any? { |json| json['name'] == branch }
end

def request_method
def request_method_for_commit
response = connection.get "projects/#{repo_id}/repository/files?ref=#{branch}&file_path=#{filename}"
response.status == 404 ? :post : :put
end
Expand Down
20 changes: 18 additions & 2 deletions lib/jekyll/gitlab/letsencrypt/process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ def process!
wait_until_challenge_is_present
request_verification!
await_verification_confirmation
display_certificate
if update_gitlab_pages
Jekyll.logger.info "Success!"
else
Jekyll.logger.info "Updating certificate failed... manual steps:"
display_certificate
end
end

private

def commit_to_gitlab!
Jekyll.logger.info "Pushing file to Gitlab"
Commiter.new(challenge_content).commit!
gitlab_client.commit!(challenge_content)
end

def wait_until_challenge_is_present
Expand All @@ -54,6 +59,9 @@ def wait_until_challenge_is_present
def request_verification!
Jekyll.logger.info "Requesting verification..."
challenge.request_verification
rescue ::Acme::Client::Error::BadNonce
Jekyll.logger.info "bad nonce! trying again.."
challenge.request_verification
end

def await_verification_confirmation
Expand All @@ -70,6 +78,10 @@ def await_verification_confirmation
end
end

def update_gitlab_pages
gitlab_client.update_certificate! certificate.fullchain_to_pem, certificate.request.private_key.to_pem
end

def display_certificate
Jekyll.logger.info "Certifcate retrieved!"
Jekyll.logger.info "Go to https://gitlab.com/#{gitlab_repo}/pages"
Expand Down Expand Up @@ -114,6 +126,10 @@ def challenge_url
end
end

def gitlab_client
@gitlab_client ||= GitlabClient.new
end

def challenge
@challenge ||= client.challenge
end
Expand Down
6 changes: 2 additions & 4 deletions spec/lib/jekyll/gitlab/letsencrypt/acme_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@
end

describe '#client' do
it 'returns a new ACME client fitted with a new private key' do
expect(OpenSSL::PKey::RSA).to receive(:new).with(4096).and_return :some_key
expect(acme.client.private_key).to eq :some_key
expect(acme.client.endpoint).to eq endpoint
it 'returns a new ACME client' do
expect(acme.client.endpoint).to eq endpoint
end
end
end
27 changes: 0 additions & 27 deletions spec/lib/jekyll/gitlab/letsencrypt/committer_spec.rb

This file was deleted.

56 changes: 56 additions & 0 deletions spec/lib/jekyll/gitlab/letsencrypt/gitlab_client_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'spec_helper'

describe Jekyll::Gitlab::Letsencrypt::GitlabClient do
let(:gitlab_client) { described_class.new }
let(:content) { '<CONTENT>' }

let(:filename) { 'test_file.html' }
let(:personal_access_token) { 'SECRET_TOKEN' }
let(:gitlab_repo) { 'gitlab_user/gitlab_repo' }
let(:branch) { 'test_branch' }
let(:domain) { 'example.com' }

before do
allow(Jekyll::Gitlab::Letsencrypt::Configuration).to receive(:filename).and_return filename
allow(Jekyll::Gitlab::Letsencrypt::Configuration).to receive(:personal_access_token).and_return personal_access_token
allow(Jekyll::Gitlab::Letsencrypt::Configuration).to receive(:gitlab_repo).and_return gitlab_repo
allow(Jekyll::Gitlab::Letsencrypt::Configuration).to receive(:branch).and_return branch
allow(Jekyll::Gitlab::Letsencrypt::Configuration).to receive(:domain).and_return domain
end

describe "#commit!" do
it 'creates the branch and shit' do
VCR.use_cassette 'gitlab_commit' do
expect(Jekyll.logger).to receive(:info).with "Creating branch test_branch.."
expect(Jekyll.logger).to receive(:info).with "Commiting challenge file as test_file.html"
expect(Jekyll.logger).to receive(:info).with "Done Commiting! Check https://gitlab.com/gitlab_user/gitlab_repo/commits/test_branch"
gitlab_client.commit! content
end
end
end

describe "#update_certificate!" do
let(:mock_connection) { double Faraday::Connection, put: response }

before do
expect(Jekyll.logger).to receive(:info).with "Updating domain example.com pages setting with new certificates.."
allow(gitlab_client).to receive(:connection).and_return mock_connection
end

context "successful" do
let(:response) { double Faraday::Response, success?: true }

it "returns true" do
expect(gitlab_client.update_certificate! :foo, :bar).to eq true
end
end

context "unsuccessful" do
let(:response) { double Faraday::Response, success?: false }

it "returns false" do
expect(gitlab_client.update_certificate! :foo, :bar).to eq false
end
end
end
end
3 changes: 2 additions & 1 deletion spec/lib/jekyll/gitlab/letsencrypt/process_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
allow(process).to receive :wait_until_challenge_is_present
allow(process).to receive :request_verification!
allow(process).to receive :await_verification_confirmation
allow(process).to receive :update_gitlab_pages
allow(process).to receive :display_certificate
end

Expand All @@ -19,7 +20,7 @@
before { allow(client).to receive(:authorized?).and_return true }

it 'bails early' do
expect(Jekyll).to receive_message_chain(:logger, :abort_with).with "Client is already authorized."
expect(Jekyll.logger).to receive(:abort_with).with("Client is already authorized.")
end
end

Expand Down

0 comments on commit 5694e04

Please sign in to comment.