diff --git a/.devcontainer/app_reg_db.json b/.devcontainer/app_reg_db.json new file mode 100644 index 0000000..c5a452e --- /dev/null +++ b/.devcontainer/app_reg_db.json @@ -0,0 +1,11 @@ +{ + "domain-names": [ + { + "id": "example.com", + "fullyQualifiedDomainName": "example.com", + "ownerDelegatedRequestToTeam": true, + "autoApprovedGroups": "group1", + "autoApprovedServiceAccounts": "john.doe@example.com" + } + ] +} \ No newline at end of file diff --git a/.devcontainer/app_reg_routes.json b/.devcontainer/app_reg_routes.json new file mode 100644 index 0000000..ba3845e --- /dev/null +++ b/.devcontainer/app_reg_routes.json @@ -0,0 +1,3 @@ +{ + "/api/v1beta1/*": "/$1" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 56426d5..350315d 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -19,6 +19,8 @@ services: VAULT_ADDR: http://10.1.10.100:8200 VAULT_TOKEN: root_token JWT_SIGNING_KEY: jwt_secret + APP_REGISTRY_ADDR: http://10.1.10.150:8800 + APP_REGISTRY_TOKEN: app_reg_token vault: image: hashicorp/vault:latest @@ -32,6 +34,20 @@ services: astral: ipv4_address: "10.1.10.100" + app_registry: + image: node:latest + restart: unless-stopped + ports: + - 8800:8800 + volumes: + - .:/data + networks: + astral: + ipv4_address: "10.1.10.150" + command: > + sh -c "npm install -g json-server@0.17.4 && + json-server /data/app_reg_db.json --routes /data/app_reg_routes.json --port 8800 --host 0.0.0.0" + networks: astral: ipam: diff --git a/app/interactors/refresh_domain.rb b/app/interactors/refresh_domain.rb index 0c1c9b9..f9ea517 100644 --- a/app/interactors/refresh_domain.rb +++ b/app/interactors/refresh_domain.rb @@ -4,7 +4,6 @@ class RefreshDomain def call domain_info = Services::DomainOwnershipService.new.get_domain_info(context.request.fqdn) domain_record = Domain.first_or_create(fqdn: context.request.fqdn) - if !domain_info domain_record.delete return diff --git a/app/lib/services/auth_service.rb b/app/lib/services/auth_service.rb index 1006e8f..c0b723f 100644 --- a/app/lib/services/auth_service.rb +++ b/app/lib/services/auth_service.rb @@ -19,7 +19,7 @@ def authorize!(identity, cert_issue_req) def decode(token) # Decode a JWT access token using the configured base. - body = JWT.decode(token, Rails.application.configuration.astral[:jwt_signing_key])[0] + body = JWT.decode(token, Rails.configuration.astral[:jwt_signing_key])[0] Identity.new(body) rescue => e Rails.logger.warn "Unable to decode token: #{e}" diff --git a/app/lib/services/domain_ownership_service.rb b/app/lib/services/domain_ownership_service.rb index b2e1cb9..33bd7fc 100644 --- a/app/lib/services/domain_ownership_service.rb +++ b/app/lib/services/domain_ownership_service.rb @@ -3,12 +3,17 @@ class DomainOwnershipService attr_reader :client def initialize - @client = Faraday.new(url: Rails.configuration.astral[:app_registry_uri]) do |faraday| + @client = Faraday.new(ssl: ssl_opts, url: Rails.configuration.astral[:app_registry_addr]) do |faraday| + faraday.request :authorization, "Bearer", -> { Rails.configuration.astral[:app_registry_token] } + faraday.request :retry, retry_opts + faraday.response :json faraday.response :raise_error, include_request: true end end - def get_domain_info + def get_domain_info(fqdn) + rslt = client.get("/api/v1beta1/domain-names/#{fqdn}").body + convert(rslt) end private @@ -19,11 +24,28 @@ def convert(input) end OpenStruct.new( - fqdn: domain_info["fullyQualifiedDomainName"], - group_delegation: domain_info["ownerDelegatedRequestsToTeam"], - groups: domain_info["autoApprovedGroups"], - users: domain_info["autoApprovedServiceAccounts"] - ) + fqdn: domain_info["fullyQualifiedDomainName"], + group_delegation: domain_info["ownerDelegatedRequestsToTeam"], + groups: domain_info["autoApprovedGroups"], + users: domain_info["autoApprovedServiceAccounts"] + ) + end + + def ssl_opts + { + ca_file: Rails.configuration.astral[:app_registry_ca_file], + client_cert: Rails.configuration.astral[:app_registry_client_cert], + client_key: Rails.configuration.astral[:app_registry_client_key] + } + end + + def retry_opts + { + max: 3, + interval: 0.05, + interval_randomness: 0.5, + backoff_factor: 2 + } end end end diff --git a/app/lib/services/vault_service.rb b/app/lib/services/vault_service.rb index 46327ea..3e8b383 100644 --- a/app/lib/services/vault_service.rb +++ b/app/lib/services/vault_service.rb @@ -3,15 +3,15 @@ class VaultService def initialize # TODO create a new token for use in the session @client = Vault::Client.new( - address: Rails.application.configuration.astral[:vault_addr], - token: Rails.application.configuration.astral[:vault_token] + address: Rails.configuration.astral[:vault_addr], + token: Rails.configuration.astral[:vault_token] ) end def issue_cert(cert_issue_request) opts = cert_issue_request.attributes # Generate the TLS certificate using the intermediate CA - tls_cert = @client.logical.write(Rails.application.configuration.astral[:vault_cert_path], opts) + tls_cert = @client.logical.write(Rails.configuration.astral[:vault_cert_path], opts) OpenStruct.new tls_cert.data end end diff --git a/config/astral.yml b/config/astral.yml index 0438643..f4d61c6 100644 --- a/config/astral.yml +++ b/config/astral.yml @@ -6,6 +6,9 @@ shared: cert_ttl: <%= ENV["CERT_TTL"] %> app_registry_addr: <%= ENV["APP_REGISTRY_ADDR"] %> app_registry_token: <%= ENV["APP_REGISTRY_TOKEN"] %> + app_registry_ca_file: <%= ENV["APP_REGISTRY_CA_FILE"] %> + app_registry_client_cert: <%= ENV["APP_REGISTRY_CLIENT_CERT"] %> + app_registry_client_key: <%= ENV["APP_REGISTRY_CLIENT_KEY"] %> test: cert_ttl: <%= 24.hours.in_seconds %>