From b314f104279782032cda3c46706ebf8fe5ca2b03 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Mon, 6 Feb 2023 16:52:12 -0700 Subject: [PATCH 01/42] Initial work on internal Policy Template Factory --- .../policy_factories_controller.rb | 37 ++++++++++ .../factory/create_from_policy_factory.rb | 35 ++++++++++ app/domain/factory/render_policy.rb | 11 +++ app/domain/factory/templates/base_policy.rb | 41 +++++++++++ app/domain/factory/templates/core/group.rb | 54 +++++++++++++++ .../factory/templates/core/managed_policy.rb | 56 +++++++++++++++ app/domain/factory/templates/core/policy.rb | 62 +++++++++++++++++ app/domain/factory/templates/core/user.rb | 54 +++++++++++++++ config/routes.rb | 3 + lib/tasks/policy_factory.rake | 68 +++++++++++++++++++ 10 files changed, 421 insertions(+) create mode 100644 app/controllers/policy_factories_controller.rb create mode 100644 app/domain/factory/create_from_policy_factory.rb create mode 100644 app/domain/factory/render_policy.rb create mode 100644 app/domain/factory/templates/base_policy.rb create mode 100644 app/domain/factory/templates/core/group.rb create mode 100644 app/domain/factory/templates/core/managed_policy.rb create mode 100644 app/domain/factory/templates/core/policy.rb create mode 100644 app/domain/factory/templates/core/user.rb create mode 100644 lib/tasks/policy_factory.rake diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb new file mode 100644 index 0000000000..dd03e82621 --- /dev/null +++ b/app/controllers/policy_factories_controller.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'base64' +require 'json' + +class PolicyFactoriesController < RestController + include AuthorizeResource + + before_action :current_user + + def create + factory_resource = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) + authorize(:execute, factory_resource) + + Factory::CreateFromPolicyFactory.new.call( + account: params[:account], + factory_template: JSON.parse(Base64.decode64(factory_resource.secret.value)), + request_body: JSON.parse(request.body.read), + authorization: request.headers["Authorization"] + ) + end + + def info + factory_resource = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) + authorize(:execute, factory_resource) + + template = JSON.parse(Base64.decode64(factory_resource.secret.value)) + render(json: template['schema']) + end + + private + + def load_factory(kind:, id:, account:) + Resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] + end + +end diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb new file mode 100644 index 0000000000..a2b44171e8 --- /dev/null +++ b/app/domain/factory/create_from_policy_factory.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'base64' +require 'rest_client' +require 'factory/render_policy' + +module Factory + class CreateFromPolicyFactory + def initialize(base64: Base64, renderer: Factory::RenderPolicy.new, http: RestClient) + @base64 = base64 + @renderer = renderer + @http = http + end + + def call(factory_template:, request_body:, account:, authorization:) + # Strip any attributes not defined in the JSON schema + json_params = factory_template['schema']['properties'].keys + template_params = request_body.select { |k, _| json_params.include?(k) } + + # Verify the required JSON attributes are present in the JSON request body + missing_params = factory_template['schema']['required'].difference(template_params.keys) + unless (missing_params.empty?) + raise "The following JSON parameters are missing from the request: '#{missing_params.join("','")}'" + end + + # Render the policy from the template and provided values + policy_template = @base64.decode64(factory_template['policy']) + policy = @renderer.render(policy_template: policy_template, variables: template_params) + + # Push rendered policy to the desired policy branch + @http.post("http://localhost:3000/policies/#{account}/policy/#{template_params['branch']}", policy, 'Authorization' => authorization) + + end + end +end diff --git a/app/domain/factory/render_policy.rb b/app/domain/factory/render_policy.rb new file mode 100644 index 0000000000..53cc24a27d --- /dev/null +++ b/app/domain/factory/render_policy.rb @@ -0,0 +1,11 @@ +module Factory + class RenderPolicy + def initialize(render_engine: ERB) + @render_engine = render_engine + end + + def render(policy_template:, variables:) + @render_engine.new(policy_template, nil, '-').result_with_hash(variables) + end + end +end diff --git a/app/domain/factory/templates/base_policy.rb b/app/domain/factory/templates/base_policy.rb new file mode 100644 index 0000000000..732fe28e59 --- /dev/null +++ b/app/domain/factory/templates/base_policy.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Factory + module Templates + class BasePolicy + class << self + def policy + <<~TEMPLATE + - !policy + id: conjur + body: + - !policy + id: factories + body: + - !policy + id: core + body: + - !variable user + - !variable host + - !variable group + - !variable policy + - !variable layer + - !variable grant + - !variable permit + - !variable managed-policy + - !policy + id: authenticators + body: + - !variable authn-azure + - !variable authn-iam + - !variable authn-oidc + - !variable authn-ldap + - !variable authn-k8s + - !variable authn-gcp + - !variable authn-jwt + TEMPLATE + end + end + end + end +end diff --git a/app/domain/factory/templates/core/group.rb b/app/domain/factory/templates/core/group.rb new file mode 100644 index 0000000000..9287a01f17 --- /dev/null +++ b/app/domain/factory/templates/core/group.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Core + class Group + class << self + def policy_template + <<~TEMPLATE + - !group + id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + schema: { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "Group Template", + "description": "Creates a Conjur Group", + "type": "object", + "properties": { + "id": { + "description": "Group ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this group into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the group", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/core/managed_policy.rb b/app/domain/factory/templates/core/managed_policy.rb new file mode 100644 index 0000000000..984a5b87ac --- /dev/null +++ b/app/domain/factory/templates/core/managed_policy.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Core + class ManagedPolicy + class << self + def policy_template + <<~TEMPLATE + - !group <%= name %>-admins + - !policy + id: <%= name %> + owner: !group <%= name %>-admins + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + schema: { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "Managed Policy Template", + "description": "Policy with an owner group", + "type": "object", + "properties": { + "name": { + "description": "Policy name (used to create the policy ID and the -admins owner group)", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this policy into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[name branch] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/core/policy.rb b/app/domain/factory/templates/core/policy.rb new file mode 100644 index 0000000000..1457a0d082 --- /dev/null +++ b/app/domain/factory/templates/core/policy.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Core + class Policy + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + <% if defined?(owner) %> + owner: <%= owner %> + <% end %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + schema: { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "User Template", + "description": "Creates a Conjur Policy", + "type": "object", + "properties": { + "id": { + "description": "Policy ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this policy into", + "type": "string" + }, + "owner": { + "description": "Optional owner of this policy", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + + end + end +end diff --git a/app/domain/factory/templates/core/user.rb b/app/domain/factory/templates/core/user.rb new file mode 100644 index 0000000000..19a50e1a86 --- /dev/null +++ b/app/domain/factory/templates/core/user.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Core + class User + class << self + def policy_template + <<~TEMPLATE + - !user + id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + schema: { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "User Template", + "description": "Creates a Conjur User", + "type": "object", + "properties": { + "id": { + "description": "User ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this user into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index e1f4db4a66..61ee9ed186 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,6 +51,9 @@ def matches?(request) post '/authn-k8s/:service_id/inject_client_cert' => 'authenticate#k8s_inject_client_cert' end + post "/factory/:account/:kind/:id" => "policy_factories#create" + get "/factory/:account/:kind/:id" => "policy_factories#info" + get "/roles/:account/:kind/*identifier" => "roles#graph", :constraints => QueryParameterActionRecognizer.new("graph") get "/roles/:account/:kind/*identifier" => "roles#all_memberships", :constraints => QueryParameterActionRecognizer.new("all") get "/roles/:account/:kind/*identifier" => "roles#direct_memberships", :constraints => QueryParameterActionRecognizer.new("memberships") diff --git a/lib/tasks/policy_factory.rake b/lib/tasks/policy_factory.rake new file mode 100644 index 0000000000..0ea91bae15 --- /dev/null +++ b/lib/tasks/policy_factory.rake @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + class ValidateTemplate + def initialize(renderer: Factory::RenderPolicy.new) + @renderer = renderer + end + + def test(factory:, template_params:) + puts('template:') + puts(factory.policy_template) + puts('--------------') + puts('') + puts('rendered template:') + puts(@renderer.render(policy_template: factory.policy_template, variables: template_params)) + + # puts(ERB.new(@factory.policy_template, nil, '-').result_with_hash(args)) + end + end + end +end + +namespace :policy_factory do + def api_key + return ENV['CONJUR_AUTHN_API_KEY'] if ENV.key?('CONJUR_AUTHN_API_KEY') + + raise 'Conjur `admin` user API key must be provided via `CONJUR_AUTHN_API_KEY` environment variable' + end + + def client + @client ||= begin + Conjur.configuration.account = 'cucumber' + Conjur.configuration.appliance_url = 'http://localhost:3000/' + Conjur::API.new_from_key('admin', api_key) + end + end + + task test: :environment do + tester = Factory::Templates::ValidateTemplate.new + tester.test( + factory: Factory::Templates::Core::Group, + template_params: { "id"=>"test-group", "branch"=>"root", "annotations"=>{ "one"=>1, "two"=>2, "test/three"=>3 } } + ) + tester.test( + factory: Factory::Templates::Core::Group, + template_params: { "id"=>"test-group", "branch"=>"root" } + ) + end + + task load: :environment do + client.load_policy('root', Factory::Templates::BasePolicy.policy) + client.resource('cucumber:variable:conjur/factories/core/group').add_value(Factory::Templates::Core::Group.data) + client.resource('cucumber:variable:conjur/factories/core/managed-policy').add_value(Factory::Templates::Core::ManagedPolicy.data) + client.resource('cucumber:variable:conjur/factories/core/policy').add_value(Factory::Templates::Core::Policy.data) + client.resource('cucumber:variable:conjur/factories/core/user').add_value(Factory::Templates::Core::User.data) + end + + task retrieve_auth_token: :environment do + url = 'http://localhost:3000/' + username = 'admin' + + response = RestClient.post("#{url}/authn/cucumber/#{username}/authenticate", api_key, 'Accept-Encoding' => 'base64') + puts response.body + end +end From efa23ceef83ee8c99b96e3f384fab08ea3b98e4e Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 9 Feb 2023 15:30:42 -0700 Subject: [PATCH 02/42] Second round of revisions --- Gemfile | 2 + Gemfile.lock | 11 ++ .../policy_factories_controller.rb | 4 +- .../factory/create_from_policy_factory.rb | 57 +++++++-- .../templates/authenticators/authn_oidc.rb | 102 ++++++++++++++++ app/domain/factory/templates/base_policy.rb | 34 +++--- .../factory/templates/connections/database.rb | 95 +++++++++++++++ app/domain/factory/templates/core/group.rb | 4 +- .../factory/templates/core/managed_policy.rb | 4 +- app/domain/factory/templates/core/policy.rb | 4 +- app/domain/factory/templates/core/user.rb | 4 +- lib/tasks/policy_factory.rake | 2 + .../create_from_policy_factory_spec.rb | 110 ++++++++++++++++++ 13 files changed, 397 insertions(+), 36 deletions(-) create mode 100644 app/domain/factory/templates/authenticators/authn_oidc.rb create mode 100644 app/domain/factory/templates/connections/database.rb create mode 100644 spec/app/domain/factory/create_from_policy_factory_spec.rb diff --git a/Gemfile b/Gemfile index 1f06d52394..3ae65bcd57 100644 --- a/Gemfile +++ b/Gemfile @@ -77,6 +77,8 @@ gem 'openid_connect' gem "anyway_config" gem 'i18n', '~> 1.8.11' +gem 'json_schemer' + group :development, :test do gem 'aruba' gem 'ci_reporter_rspec' diff --git a/Gemfile.lock b/Gemfile.lock index e3dac5d981..a8530fc27a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -203,6 +203,8 @@ GEM dry-core (~> 0.5, >= 0.5) dry-inflector (~> 0.1, >= 0.1.2) dry-logic (~> 1.0, >= 1.0.2) + ecma-re-validator (0.4.0) + regexp_parser (~> 2.2) erubi (1.12.0) event_emitter (0.2.6) eventmachine (1.2.7) @@ -218,6 +220,7 @@ GEM globalid (1.0.1) activesupport (>= 5.0) haikunator (1.1.1) + hana (1.3.7) hashdiff (1.0.1) highline (2.0.3) http (4.2.0) @@ -245,6 +248,11 @@ GEM activesupport (>= 4.2) aes_key_wrap bindata + json_schemer (0.2.24) + ecma-re-validator (~> 0.3) + hana (~> 1.3) + regexp_parser (~> 2.0) + uri_template (~> 0.7) json_spec (1.1.5) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) @@ -378,6 +386,7 @@ GEM kwalify (~> 0.7.0) parser (~> 3.0.0) rainbow (>= 2.0, < 4.0) + regexp_parser (2.7.0) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) @@ -464,6 +473,7 @@ GEM unf_ext unf_ext (0.0.8.1) unicode-display_width (1.8.0) + uri_template (0.7.0) validate_email (0.1.6) activemodel (>= 3.0) mail (>= 2.2.5) @@ -522,6 +532,7 @@ DEPENDENCIES i18n (~> 1.8.11) iso8601 jbuilder (~> 2.7.0) + json_schemer json_spec (~> 1.1) jwt (= 2.2.2) kubeclient diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index dd03e82621..bdcabfc268 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -12,12 +12,14 @@ def create factory_resource = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) authorize(:execute, factory_resource) - Factory::CreateFromPolicyFactory.new.call( + response = Factory::CreateFromPolicyFactory.new.call( account: params[:account], factory_template: JSON.parse(Base64.decode64(factory_resource.secret.value)), request_body: JSON.parse(request.body.read), authorization: request.headers["Authorization"] ) + + render(json: JSON.parse(response.body), status: :created) if response.code == 201 end def info diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb index a2b44171e8..9f694474d5 100644 --- a/app/domain/factory/create_from_policy_factory.rb +++ b/app/domain/factory/create_from_policy_factory.rb @@ -2,34 +2,67 @@ require 'base64' require 'rest_client' +require 'json_schemer' require 'factory/render_policy' module Factory class CreateFromPolicyFactory - def initialize(base64: Base64, renderer: Factory::RenderPolicy.new, http: RestClient) + def initialize(base64: Base64, renderer: Factory::RenderPolicy.new, http: RestClient, schema_validator: JSONSchemer) @base64 = base64 @renderer = renderer @http = http + @schema_validator = schema_validator end - def call(factory_template:, request_body:, account:, authorization:) - # Strip any attributes not defined in the JSON schema - json_params = factory_template['schema']['properties'].keys - template_params = request_body.select { |k, _| json_params.include?(k) } - - # Verify the required JSON attributes are present in the JSON request body - missing_params = factory_template['schema']['required'].difference(template_params.keys) - unless (missing_params.empty?) - raise "The following JSON parameters are missing from the request: '#{missing_params.join("','")}'" + def validate!(schema:, params:) + validator = @schema_validator.schema(schema) + return if validator.valid?(params) + + error = validator.validate(params).first + case error['type'] + when 'required' + missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject{|item| item.empty?}.join('/') }.join("', '") + raise "The following JSON attributes are missing: '#{missing_attributes}'" + else + raise "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" end + end + + def call(factory_template:, request_body:, account:, authorization:) + validate!( + schema: factory_template['schema'], + params: request_body + ) + + # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. + # Conjur variables should be use dashes rather than underscores. + template_variables = request_body.transform_keys { |key| key.to_s.underscore } # Render the policy from the template and provided values policy_template = @base64.decode64(factory_template['policy']) - policy = @renderer.render(policy_template: policy_template, variables: template_params) # Push rendered policy to the desired policy branch - @http.post("http://localhost:3000/policies/#{account}/policy/#{template_params['branch']}", policy, 'Authorization' => authorization) + policy_load_path = @renderer.render(policy_template: factory_template['target_policy_namespace'], variables: template_variables) + response = @http.post( + "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", + @renderer.render(policy_template: policy_template, variables: template_variables), + 'Authorization' => authorization + ) + if factory_template['schema']['properties'].key?('variables') + variable_path = @renderer.render(policy_template: factory_template['target_variable_namespace'], variables: template_variables) + factory_template['schema']['properties']['variables']['properties'].each_key do |factory_variable| + variable_id = URI.encode_www_form_component("#{variable_path}/#{factory_variable}") + + @http.post( + "http://localhost:3000/secrets/#{account}/variable/#{variable_id}", + # All values must be sent to Conjur as strings + template_variables['variables'][factory_variable].to_s, + { 'Authorization' => authorization } + ) + end + end + response end end end diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb new file mode 100644 index 0000000000..ec63f76811 --- /dev/null +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Authenticators + class AuthnOidc + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= service_id %> + body: + - !webservice + + - !variable provider-uri + - !variable client-id + - !variable client-secret + + # URI of Conjur instance + - !variable redirect_uri + + # Defines the JWT claim to use as the Conjur identifier + - !variable claim-mapping + + - !group authenticatable + annotations: + description: Group with permission to authenticate using this authenticator + + - !permit + role: !group authenticatable + privilege: [ read, authenticate ] + resource: !webservice + + - !webservice status + annotations: + description: Web service for checking authenticator status + + - !group + id: operators + annotations: + description: Group with permission to check the authenticator status + + - !permit + role: !group operators + privilege: read + resource: !webservice status + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + target_policy_namespace: "conjur/authn-oidc", + target_variable_namespace: "conjur/authn-oidc/<%= service_id %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Managed Policy Template", + "description": "Policy with an owner group", + "type": "object", + "properties": { + "service-id": { + "description": "Service ID of the Authenticator", + "type": "string" + }, + "variables": { + "type": "object", + "properties": { + "provider-uri": { + "description": "OIDC Provider endpoint", + "type": "string" + }, + "client-id": { + "description": "OIDC Client ID", + "type": "string" + }, + "client-secret": { + "description": "OIDC Client Secret", + "type": "string" + }, + "redirect-uri": { + "description": "Target URL to redirect to after successful authentication", + "type": "string" + }, + "claim-mapping": { + "description": "OIDC JWT claim mapping. This value must match to a Conjur Host ID.", + "type": "string" + }, + }, + "required": %w[provider-uri client-id client-secret claim-mapping] + } + }, + "required": %w[service-id] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/base_policy.rb b/app/domain/factory/templates/base_policy.rb index 732fe28e59..79f2d7cf28 100644 --- a/app/domain/factory/templates/base_policy.rb +++ b/app/domain/factory/templates/base_policy.rb @@ -15,24 +15,28 @@ def policy - !policy id: core body: - - !variable user - - !variable host - - !variable group - - !variable policy - - !variable layer - - !variable grant - - !variable permit - - !variable managed-policy + - !variable user + - !variable host + - !variable group + - !variable policy + - !variable layer + - !variable grant + - !variable permit + - !variable managed-policy - !policy id: authenticators body: - - !variable authn-azure - - !variable authn-iam - - !variable authn-oidc - - !variable authn-ldap - - !variable authn-k8s - - !variable authn-gcp - - !variable authn-jwt + - !variable authn-azure + - !variable authn-iam + - !variable authn-oidc + - !variable authn-ldap + - !variable authn-k8s + - !variable authn-gcp + - !variable authn-jwt + - !policy + id: connections + body: + - !variable database TEMPLATE end end diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb new file mode 100644 index 0000000000..81561da215 --- /dev/null +++ b/app/domain/factory/templates/connections/database.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Connections + class Database + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + annotations: + factory: connections/database + body: + - &variables + - !variable url + - !variable port + - !variable username + - !variable password + + - !group consumers + - !group administrators + + # consumers can read and execute + - !permit + resource: *variables + privileges: [ read, execute ] + role: !group consumers + + # administrators can update (and read and execute, via role grant) + - !permit + resource: *variables + privileges: [ update ] + role: !group administrators + + # administrators has role consumers + - !grant + member: !group administrators + role: !group consumers + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", + target_variable_namespace: "<%= branch %>/<%= id %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Database Connection Template", + "description": "All information for connecting to a database", + "type": "object", + "properties": { + "id": { + "description": "Database Connection ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this database connection into", + "type": "string" + }, + "variables": { + "type": "object", + "properties": { + "url": { + "description": "Database URL", + "type": "string" + }, + "port": { + "description": "Database Port", + "type": "integer" + }, + "username": { + "description": "Database Username", + "type": "string" + }, + "password": { + "description": "Database Password", + "type": "string" + }, + }, + "required": %w[url port username password] + } + }, + "required": %w[id branch variables] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/core/group.rb b/app/domain/factory/templates/core/group.rb index 9287a01f17..48ed26d7e6 100644 --- a/app/domain/factory/templates/core/group.rb +++ b/app/domain/factory/templates/core/group.rb @@ -23,9 +23,9 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", schema: { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/product.schema.json", + "$schema": "http://json-schema.org/draft-06/schema#", "title": "Group Template", "description": "Creates a Conjur Group", "type": "object", diff --git a/app/domain/factory/templates/core/managed_policy.rb b/app/domain/factory/templates/core/managed_policy.rb index 984a5b87ac..cec330afcd 100644 --- a/app/domain/factory/templates/core/managed_policy.rb +++ b/app/domain/factory/templates/core/managed_policy.rb @@ -25,9 +25,9 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", schema: { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/product.schema.json", + "$schema": "http://json-schema.org/draft-06/schema#", "title": "Managed Policy Template", "description": "Policy with an owner group", "type": "object", diff --git a/app/domain/factory/templates/core/policy.rb b/app/domain/factory/templates/core/policy.rb index 1457a0d082..36f7818a0e 100644 --- a/app/domain/factory/templates/core/policy.rb +++ b/app/domain/factory/templates/core/policy.rb @@ -26,9 +26,9 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", schema: { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/product.schema.json", + "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", "description": "Creates a Conjur Policy", "type": "object", diff --git a/app/domain/factory/templates/core/user.rb b/app/domain/factory/templates/core/user.rb index 19a50e1a86..6aa962fba1 100644 --- a/app/domain/factory/templates/core/user.rb +++ b/app/domain/factory/templates/core/user.rb @@ -23,9 +23,9 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", schema: { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/product.schema.json", + "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", "description": "Creates a Conjur User", "type": "object", diff --git a/lib/tasks/policy_factory.rake b/lib/tasks/policy_factory.rake index 0ea91bae15..a6da1ca62c 100644 --- a/lib/tasks/policy_factory.rake +++ b/lib/tasks/policy_factory.rake @@ -56,6 +56,8 @@ namespace :policy_factory do client.resource('cucumber:variable:conjur/factories/core/managed-policy').add_value(Factory::Templates::Core::ManagedPolicy.data) client.resource('cucumber:variable:conjur/factories/core/policy').add_value(Factory::Templates::Core::Policy.data) client.resource('cucumber:variable:conjur/factories/core/user').add_value(Factory::Templates::Core::User.data) + client.resource('cucumber:variable:conjur/factories/authenticators/authn-oidc').add_value(Factory::Templates::Authenticators::AuthnOidc.data) + client.resource('cucumber:variable:conjur/factories/connections/database').add_value(Factory::Templates::Connections::Database.data) end task retrieve_auth_token: :environment do diff --git a/spec/app/domain/factory/create_from_policy_factory_spec.rb b/spec/app/domain/factory/create_from_policy_factory_spec.rb new file mode 100644 index 0000000000..ced73f183f --- /dev/null +++ b/spec/app/domain/factory/create_from_policy_factory_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe(Factory::CreateFromPolicyFactory) do + let(:rest_client) { spy(RestClient) } + let(:factory) { Factory::CreateFromPolicyFactory.new(http: rest_client) } + + describe('.call') do + # let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)) } + context 'when request is missing attributes' do + it 'fails with error' do + expect { + factory.call( + factory_template: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)), + request_body: { 'id' => 'foo' }, + account: 'cucumber', + authorization: 'bar' + ) + }.to raise_error(RuntimeError, "The following JSON attributes are missing: 'branch'") + end + end + context 'when request is missing nested attributes' do + it 'fails with error' do + expect { + factory.call( + factory_template: JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)), + request_body: { + 'service-id' => 'foo', + 'variables' => { + 'provider-uri' => 'foo', + 'client-id' => 'bar', + 'client-secret' => 'baz' + } + }, + account: 'cucumber', + authorization: 'bar' + ) + }.to raise_error(RuntimeError, "The following JSON attributes are missing: '/variables/claim-mapping'") + end + end + + context 'when policy factory is only a policy' do + it 'loads the appropriate policy' do + factory.call( + factory_template: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)), + request_body: { 'id' => 'foo', 'branch' => 'bar' }, + account: 'cucumber', + authorization: 'bar' + ) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}) + end + end + + context 'when policy factory is policy and variables' do + let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)) } + before do + factory.call( + factory_template: factory_template, + request_body: { + 'service-id' => 'foo', + 'variables' => { + 'provider-uri' => 'foo', + 'client-id' => 'bar', + 'client-secret' => 'baz', + 'claim-mapping' => 'bing' + } + }, + account: 'cucumber', + authorization: 'bar' + ) + end + it 'loads the appropriate policy' do + expect(rest_client).to have_received(:post).with( + 'http://localhost:3000/policies/cucumber/policy/conjur/authn-oidc', + "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n\n # URI of Conjur instance\n - !variable redirect_uri\n\n # Defines the JWT claim to use as the Conjur identifier\n - !variable claim-mapping\n\n - !group authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: read\n resource: !webservice status\n", + { "Authorization"=>"bar" } + ) + end + it 'sets provider-id to the expected value' do + expect(rest_client).to have_received(:post).with( + 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fprovider-uri', + 'foo', + { 'Authorization' => 'bar' } + ) + end + it 'sets client-id to the expected value' do + expect(rest_client).to have_received(:post).with( + 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-id', + 'bar', + { 'Authorization' => 'bar' } + ) + end + it 'sets client-secret to the expected value' do + expect(rest_client).to have_received(:post).with( + 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-secret', + 'baz', + { 'Authorization' => 'bar' } + ) + end + it 'sets claim-mapping to the expected value' do + expect(rest_client).to have_received(:post).with( + 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclaim-mapping', + 'bing', + { 'Authorization' => 'bar' } + ) + end + end + end +end From 543df69142ee3ae64f8790fa628560ecd686dedc Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 10 Feb 2023 15:47:31 -0700 Subject: [PATCH 03/42] small fixes, including - updates to policy - filter empty request params --- Gemfile.lock | 18 +++++++++--------- .../factory/create_from_policy_factory.rb | 1 + .../templates/authenticators/authn_oidc.rb | 14 ++++++++------ .../factory/templates/connections/database.rb | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a8530fc27a..4bd9cbab8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,8 +67,8 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) aes_key_wrap (1.1.0) anyway_config (2.2.3) ruby-next-core (>= 0.14.0) @@ -107,8 +107,8 @@ GEM rspec (>= 2.14, < 4) coderay (1.1.3) command_class (0.0.2) - concurrent-ruby (1.1.10) - conjur-api (5.3.8.pre.194) + concurrent-ruby (1.2.0) + conjur-api (5.4.0) activesupport (>= 4.2) addressable (~> 2.0) rest-client @@ -229,7 +229,7 @@ GEM http-form_data (~> 2.0) http-parser (~> 1.2.0) http-accept (1.7.0) - http-cookie (1.0.4) + http-cookie (1.0.5) domain_name (~> 0.5) http-form_data (2.3.0) http-parser (1.2.3) @@ -325,7 +325,7 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.6) + public_suffix (5.0.1) puma (5.6.4) nio4r (~> 2.0) racc (1.6.2) @@ -467,11 +467,11 @@ GEM table_print (1.5.7) thor (1.2.1) timeout (0.3.1) - tzinfo (2.0.5) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.1) + unf_ext (0.0.8.2) unicode-display_width (1.8.0) uri_template (0.7.0) validate_email (0.1.6) @@ -494,7 +494,7 @@ GEM websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xdg (2.2.3) - zeitwerk (2.6.6) + zeitwerk (2.6.7) PLATFORMS x86_64-darwin-20 diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb index 9f694474d5..a78a3ce021 100644 --- a/app/domain/factory/create_from_policy_factory.rb +++ b/app/domain/factory/create_from_policy_factory.rb @@ -29,6 +29,7 @@ def validate!(schema:, params:) end def call(factory_template:, request_body:, account:, authorization:) + request_body = request_body.select{|_,v| v.present? } validate!( schema: factory_template['schema'], params: request_body diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb index ec63f76811..ca5cd15241 100644 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -19,12 +19,13 @@ def policy_template - !variable client-secret # URI of Conjur instance - - !variable redirect_uri + - !variable redirect-uri # Defines the JWT claim to use as the Conjur identifier - !variable claim-mapping - - !group authenticatable + - !group + id: authenticatable annotations: description: Group with permission to authenticate using this authenticator @@ -33,7 +34,8 @@ def policy_template privilege: [ read, authenticate ] resource: !webservice - - !webservice status + - !webservice + id: status annotations: description: Web service for checking authenticator status @@ -44,7 +46,7 @@ def policy_template - !permit role: !group operators - privilege: read + privilege: [ read ] resource: !webservice status TEMPLATE end @@ -56,8 +58,8 @@ def data target_variable_namespace: "conjur/authn-oidc/<%= service_id %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Managed Policy Template", - "description": "Policy with an owner group", + "title": "Authn-OIDC Template", + "description": "Create a new Authn-OIDC Authenticator", "type": "object", "properties": { "service-id": { diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb index 81561da215..576c851eb6 100644 --- a/app/domain/factory/templates/connections/database.rb +++ b/app/domain/factory/templates/connections/database.rb @@ -70,7 +70,7 @@ def data }, "port": { "description": "Database Port", - "type": "integer" + "type": "string" }, "username": { "description": "Database Username", From 950d747d428f0d3258c990e91cae212b6ef2417b Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Tue, 21 Feb 2023 09:00:19 -0700 Subject: [PATCH 04/42] Moves from Service ID to ID --- .../factory/create_from_policy_factory.rb | 8 +-- app/domain/factory/render_policy.rb | 4 +- .../templates/authenticators/authn_oidc.rb | 15 ++-- .../factory/templates/connections/database.rb | 3 +- app/domain/factory/templates/core/group.rb | 2 +- .../factory/templates/core/managed_policy.rb | 2 +- app/domain/factory/templates/core/policy.rb | 2 +- app/domain/factory/templates/core/user.rb | 2 +- .../create_from_policy_factory_spec.rb | 6 +- spec/app/domain/factory/shared.rb | 72 +++++++++++++++++++ .../authenticators/authn_oidc_spec.rb | 26 +++++++ 11 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 spec/app/domain/factory/shared.rb create mode 100644 spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb index a78a3ce021..5d30385558 100644 --- a/app/domain/factory/create_from_policy_factory.rb +++ b/app/domain/factory/create_from_policy_factory.rb @@ -29,7 +29,7 @@ def validate!(schema:, params:) end def call(factory_template:, request_body:, account:, authorization:) - request_body = request_body.select{|_,v| v.present? } + request_body = request_body.select{|_, v| v.present? } validate!( schema: factory_template['schema'], params: request_body @@ -43,15 +43,15 @@ def call(factory_template:, request_body:, account:, authorization:) policy_template = @base64.decode64(factory_template['policy']) # Push rendered policy to the desired policy branch - policy_load_path = @renderer.render(policy_template: factory_template['target_policy_namespace'], variables: template_variables) + policy_load_path = @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) response = @http.post( "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", - @renderer.render(policy_template: policy_template, variables: template_variables), + @renderer.render(template: policy_template, variables: template_variables), 'Authorization' => authorization ) if factory_template['schema']['properties'].key?('variables') - variable_path = @renderer.render(policy_template: factory_template['target_variable_namespace'], variables: template_variables) + variable_path = @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) factory_template['schema']['properties']['variables']['properties'].each_key do |factory_variable| variable_id = URI.encode_www_form_component("#{variable_path}/#{factory_variable}") diff --git a/app/domain/factory/render_policy.rb b/app/domain/factory/render_policy.rb index 53cc24a27d..bfe987eb4c 100644 --- a/app/domain/factory/render_policy.rb +++ b/app/domain/factory/render_policy.rb @@ -4,8 +4,8 @@ def initialize(render_engine: ERB) @render_engine = render_engine end - def render(policy_template:, variables:) - @render_engine.new(policy_template, nil, '-').result_with_hash(variables) + def render(template:, variables:) + @render_engine.new(template, nil, '-').result_with_hash(variables) end end end diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb index ca5cd15241..10633e0c7b 100644 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -10,18 +10,14 @@ class << self def policy_template <<~TEMPLATE - !policy - id: <%= service_id %> + id: <%= id %> body: - !webservice - !variable provider-uri - !variable client-id - !variable client-secret - - # URI of Conjur instance - !variable redirect-uri - - # Defines the JWT claim to use as the Conjur identifier - !variable claim-mapping - !group @@ -54,15 +50,14 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "conjur/authn-oidc", - target_variable_namespace: "conjur/authn-oidc/<%= service_id %>", + policy_namespace: "conjur/authn-oidc", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Authn-OIDC Template", "description": "Create a new Authn-OIDC Authenticator", "type": "object", "properties": { - "service-id": { + "id": { "description": "Service ID of the Authenticator", "type": "string" }, @@ -88,12 +83,12 @@ def data "claim-mapping": { "description": "OIDC JWT claim mapping. This value must match to a Conjur Host ID.", "type": "string" - }, + } }, "required": %w[provider-uri client-id client-secret claim-mapping] } }, - "required": %w[service-id] + "required": %w[id variables] } }.to_json) end diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb index 576c851eb6..a06651bd06 100644 --- a/app/domain/factory/templates/connections/database.rb +++ b/app/domain/factory/templates/connections/database.rb @@ -45,8 +45,7 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "<%= branch %>", - target_variable_namespace: "<%= branch %>/<%= id %>", + policy_namespace: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Database Connection Template", diff --git a/app/domain/factory/templates/core/group.rb b/app/domain/factory/templates/core/group.rb index 48ed26d7e6..84b91eb1f2 100644 --- a/app/domain/factory/templates/core/group.rb +++ b/app/domain/factory/templates/core/group.rb @@ -23,7 +23,7 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "<%= branch %>", + policy_namespace: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Group Template", diff --git a/app/domain/factory/templates/core/managed_policy.rb b/app/domain/factory/templates/core/managed_policy.rb index cec330afcd..82e138a16b 100644 --- a/app/domain/factory/templates/core/managed_policy.rb +++ b/app/domain/factory/templates/core/managed_policy.rb @@ -25,7 +25,7 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "<%= branch %>", + policy_namespace: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Managed Policy Template", diff --git a/app/domain/factory/templates/core/policy.rb b/app/domain/factory/templates/core/policy.rb index 36f7818a0e..086a31e0f0 100644 --- a/app/domain/factory/templates/core/policy.rb +++ b/app/domain/factory/templates/core/policy.rb @@ -26,7 +26,7 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "<%= branch %>", + policy_namespace: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", diff --git a/app/domain/factory/templates/core/user.rb b/app/domain/factory/templates/core/user.rb index 6aa962fba1..c74c1b70a8 100644 --- a/app/domain/factory/templates/core/user.rb +++ b/app/domain/factory/templates/core/user.rb @@ -23,7 +23,7 @@ def policy_template def data Base64.encode64({ policy: Base64.encode64(policy_template), - target_policy_namespace: "<%= branch %>", + policy_namespace: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", diff --git a/spec/app/domain/factory/create_from_policy_factory_spec.rb b/spec/app/domain/factory/create_from_policy_factory_spec.rb index ced73f183f..2bce24483d 100644 --- a/spec/app/domain/factory/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factory/create_from_policy_factory_spec.rb @@ -26,7 +26,7 @@ factory.call( factory_template: JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)), request_body: { - 'service-id' => 'foo', + 'id' => 'foo', 'variables' => { 'provider-uri' => 'foo', 'client-id' => 'bar', @@ -58,7 +58,7 @@ factory.call( factory_template: factory_template, request_body: { - 'service-id' => 'foo', + 'id' => 'foo', 'variables' => { 'provider-uri' => 'foo', 'client-id' => 'bar', @@ -73,7 +73,7 @@ it 'loads the appropriate policy' do expect(rest_client).to have_received(:post).with( 'http://localhost:3000/policies/cucumber/policy/conjur/authn-oidc', - "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n\n # URI of Conjur instance\n - !variable redirect_uri\n\n # Defines the JWT claim to use as the Conjur identifier\n - !variable claim-mapping\n\n - !group authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: read\n resource: !webservice status\n", + "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n - !variable redirect-uri\n - !variable claim-mapping\n\n - !group\n id: authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice\n id: status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: [ read ]\n resource: !webservice status\n", { "Authorization"=>"bar" } ) end diff --git a/spec/app/domain/factory/shared.rb b/spec/app/domain/factory/shared.rb new file mode 100644 index 0000000000..aac46f7be3 --- /dev/null +++ b/spec/app/domain/factory/shared.rb @@ -0,0 +1,72 @@ +require 'json_schemer' + +RSpec.shared_context('factory schema', shared_context: :metadata) do + context 'factory schema' do + let(:data) { JSON.parse(Base64.decode64(subject.data)) } + let(:schema) { data['schema'] } + + it 'includes policy, policy_namespace, and schema' do + data_keys = data.keys.sort + expect(data_keys).to eq(%w[policy policy_namespace schema]) + end + + context 'JSON schema is valid' do + it 'successfully validates schema' do + expect { JSONSchemer.schema(schema) }.not_to raise_error + end + end + + context 'schema defines all available properties' do + it 'includes the property: "id"' do + expect(schema['properties'].keys.sort).to eq(available_properties) + end + end + + context 'schema defines all required properties' do + it 'requires "id"' do + expect(schema['required'].sort).to eq(required_properties) + end + end + end +end + +RSpec.shared_context('factory schema with variables', shared_context: :metadata) do + context 'factory schema with variables' do + let(:data) { JSON.parse(Base64.decode64(subject.data)) } + let(:schema) { data['schema']['properties']['variables'] } + + context 'schema defines all available variables' do + it 'includes the available variable fields' do + expect(schema['properties'].keys.sort).to eq(available_variables) + end + end + + context 'schema defines all required variables' do + it 'defines the required variables' do + expect(schema['required'].sort).to eq(required_variables) + end + end + end +end + +RSpec.shared_context('policy template', shared_context: :metadata) do + context 'policy template' do + let(:data) { JSON.parse(Base64.decode64(subject.data)) } + let(:policy_template) { Base64.decode64(data['policy']) } + + context 'it includes all properties as variables' do + it 'includes relevant variables' do + (available_properties + required_properties - ['variables']).uniq.each do |property| + expect(policy_template).to include("<%= #{property} %>") + end + end + end + end +end + + +RSpec.configure do |rspec| + rspec.include_context('factory schema', include_shared: true) + rspec.include_context('factory schema with variables', include_shared: true) + rspec.include_context('policy template', include_shared: true) +end diff --git a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb new file mode 100644 index 0000000000..a4cb140f50 --- /dev/null +++ b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require './spec/app/domain/factory/shared.rb' + +RSpec.describe(Factory::Templates::Authenticators::AuthnOidc) do + subject { Factory::Templates::Authenticators::AuthnOidc } + let(:available_properties) { %w[id variables] } + let(:required_properties) { available_properties } + + let(:available_variables) { %w[claim-mapping client-id client-secret provider-uri redirect-uri] } + let(:required_variables) { %w[claim-mapping client-id client-secret provider-uri] } + + describe('#data') do + # Tests to ensure the integrity of the interface + include_context 'factory schema' + include_context 'factory schema with variables' + end + + describe('#policy_template') do + # Tests to ensure the integrity of the interface + include_context 'policy template' + # include_context 'factory schema with variables' + end +end From 2c3f5a89b07caf1ffd443ed64dbc205366cf8e2e Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Wed, 1 Mar 2023 11:54:33 -0700 Subject: [PATCH 05/42] Migrates Policy Factory to use Response objects --- .../policy_factories_controller.rb | 66 +++- app/domain/factory/Readme.md | 59 ++++ .../factory/create_from_policy_factory.rb | 223 ++++++++++--- app/domain/factory/factory_loader.rb | 37 +++ app/domain/factory/render_policy.rb | 11 - app/domain/factory/renderer.rb | 17 + app/domain/responses.rb | 52 +++ .../create_from_policy_factory_spec.rb | 308 ++++++++++++++---- .../authenticators/authn_oidc_spec.rb | 2 +- spec/app/domain/responses_spec.rb | 93 ++++++ 10 files changed, 738 insertions(+), 130 deletions(-) create mode 100644 app/domain/factory/Readme.md create mode 100644 app/domain/factory/factory_loader.rb delete mode 100644 app/domain/factory/render_policy.rb create mode 100644 app/domain/factory/renderer.rb create mode 100644 app/domain/responses.rb create mode 100644 spec/app/domain/responses_spec.rb diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index bdcabfc268..f93d0809eb 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -2,24 +2,27 @@ require 'base64' require 'json' +require './app/domain/responses' class PolicyFactoriesController < RestController - include AuthorizeResource - before_action :current_user def create - factory_resource = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) - authorize(:execute, factory_resource) - - response = Factory::CreateFromPolicyFactory.new.call( - account: params[:account], - factory_template: JSON.parse(Base64.decode64(factory_resource.secret.value)), - request_body: JSON.parse(request.body.read), - authorization: request.headers["Authorization"] - ) + response = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) + .bind do |factory| + Factory::CreateFromPolicyFactory.new.call( + account: params[:account], + factory_template: JSON.parse(Base64.decode64(factory)), + request_body: request.body.read, + authorization: request.headers["Authorization"] + ) + end - render(json: JSON.parse(response.body), status: :created) if response.code == 201 + if response.success? + render(json: JSON.parse(response.result), status: :created) + else + render(json: error_response(response), status: response.status) + end end def info @@ -32,8 +35,43 @@ def info private - def load_factory(kind:, id:, account:) - Resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] + def error_response(response) + rtn = { + status: response.status, + body: { errors: [] } + } + if response.message.is_a?(Array) + rtn[:body][:errors] == response.message + else + rtn[:body][:errors] << { + message: response.message + } + end end + def load_factory(kind:, id:, account:) + factory_resource = Resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] + if factory_resource.blank? + return ::FailureResponse.new( + "Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", + status: :not_found + ) + end + + if current_user.allowed_to?(:execute, factory_resource) + if factory_resource.secret.present? + ::SuccessResponse.new(factory_resource.secret.value) + else + ::FailureResponse.new( + "Policy Factory '#{kind}/#{id}' in account '#{account}' has not been initialized", + status: :bad_request + ) + end + else + ::FailureResponse.new( + "Role '#{current_user}' does not have access to Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", + status: :forbidden + ) + end + end end diff --git a/app/domain/factory/Readme.md b/app/domain/factory/Readme.md new file mode 100644 index 0000000000..ef33e591b4 --- /dev/null +++ b/app/domain/factory/Readme.md @@ -0,0 +1,59 @@ +# Policy Factory + +## Policy Factory Creation Requests + +```plantuml +@startuml +start +:Identify Factory\nvariable based\non request params; +if (Can role load\nfactory variable?) then + :Load Factory; + :Extract Schema from Factory; + if (Parse JSON body?) then + if (Required keys missing?) then + #pink:(400) - missing keys; + kill + else + if (required values empty?) then + #pink:(400) - missing values; + kill + else + if (Policy rendered?) then + if (Policy namespace path rendered?) then + if (Policy successfully applied) then + if (Factory has variables?) then + if (Variable successfully set?) then + :(201) Return policy response; + end + else + #pink:(401) - setting variables not permitted; + kill + endif + else + :(201) Return policy response; + end + endif + else + #pink:(401) - policy creation not permitted; + kill + endif + else + #pink:(400) - policy namespace variable(s) missing; + kill + endif + else + #pink:(400) - policy variable(s) missing; + kill + endif + endif + endif + else + #pink:(400) - malformed JSON; + kill + endif +else + #pink:(404) - factory not available; + kill +endif +@enduml +``` diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb index 5d30385558..58d9784c38 100644 --- a/app/domain/factory/create_from_policy_factory.rb +++ b/app/domain/factory/create_from_policy_factory.rb @@ -3,67 +3,200 @@ require 'base64' require 'rest_client' require 'json_schemer' -require 'factory/render_policy' +require 'factory/renderer' module Factory class CreateFromPolicyFactory - def initialize(base64: Base64, renderer: Factory::RenderPolicy.new, http: RestClient, schema_validator: JSONSchemer) - @base64 = base64 + def initialize(renderer: Factory::Renderer.new, http: RestClient, schema_validator: JSONSchemer, success: SuccessResponse, failure: FailureResponse) @renderer = renderer @http = http @schema_validator = schema_validator + @success = success + @failure = failure + + # JSON, URI, and Base64 are defined here for visibility. They + # are not currently mocked in testing, thus, we're not setting + # them in the initializer. + @json = JSON + @base64 = Base64 + @uri = URI end - def validate!(schema:, params:) + def validate_and_transform_request(schema:, params:) + return @failure.new("Request body must be JSON", status: :bad_request) if params.blank? + + begin + params = @json.parse(params) + rescue + return @failure.new("Request body must be valid JSON", status: :bad_request) + end + + # Strip keys without values + params = params.select{|_, v| v.present? } + validator = @schema_validator.schema(schema) - return if validator.valid?(params) - - error = validator.validate(params).first - case error['type'] - when 'required' - missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject{|item| item.empty?}.join('/') }.join("', '") - raise "The following JSON attributes are missing: '#{missing_attributes}'" - else - raise "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" + return @success.new(params) if validator.valid?(params) + + errors = validator.validate(params).map do |error| + case error['type'] + when 'required' + missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject(&:empty?).join('/') } #.join("', '") + missing_attributes.map do |attribute| + { + message: "Missing JSON key or value for: '#{attribute}'", + key: attribute + } + end + else + { + message: "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" + } + end + end + @failure.new(errors.flatten, status: :bad_request) + end + + def render_and_apply_policy(policy_load_path:, policy_template:, variables:, account:, authorization:) + @renderer.render( + template: policy_template, + variables: variables + ).bind do |rendered_policy| + response = @http.post( + "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", + rendered_policy, + 'Authorization' => authorization + ) + if response.code == 201 + @success.new(response.body) + else + case response.code + when 400 + @failure.new("Failed to apply generated Policy to '#{policy_load_path}'", status: :bad_request) + when 401 + @failure.new("Unauthorized to apply generated policy to '#{policy_load_path}'", status: :unauthorized) + when 403 + @failure.new("Forbidden to apply generated policy to '#{policy_load_path}'", status: :forbidden) + when 404 + @failure.new("Unable to apply generated policy to '#{policy_load_path}'", status: :not_found) + else + @failure.new( + "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", + status: :bad_request + ) + end + end + end + end + + def set_factory_variables(schema_variables:, factory_variables:, variable_path:, authorization:, account:) + schema_variables.each_key do |factory_variable| + next unless factory_variables.key?(factory_variable) + + variable_id = @uri.encode_www_form_component("#{variable_path}/#{factory_variable}") + secret_path = "secrets/#{account}/variable/#{variable_id}" + + response = @http.post( + "http://localhost:3000/#{secret_path}", + factory_variables[factory_variable].to_s, + { 'Authorization' => authorization } + ) + next if response.code == 201 + + case response.code + when 401 + return @failure.new("Role is unauthorized to set variable: '#{secret_path}'", status: :unauthorized) + when 403 + return @failure.new("Role lacks the privilege to set variable: '#{secret_path}'", status: :forbidden) + else + return @failure.new( + "Failed to set variable: '#{secret_path}'. Status Code: '#{response.code}', Response: '#{response.body}'", + status: :bad_request + ) + end end + @success.new('Variables successfully set') end def call(factory_template:, request_body:, account:, authorization:) - request_body = request_body.select{|_, v| v.present? } - validate!( + validate_and_transform_request( schema: factory_template['schema'], params: request_body - ) - - # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. - # Conjur variables should be use dashes rather than underscores. - template_variables = request_body.transform_keys { |key| key.to_s.underscore } - - # Render the policy from the template and provided values - policy_template = @base64.decode64(factory_template['policy']) - - # Push rendered policy to the desired policy branch - policy_load_path = @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) - response = @http.post( - "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", - @renderer.render(template: policy_template, variables: template_variables), - 'Authorization' => authorization - ) - - if factory_template['schema']['properties'].key?('variables') - variable_path = @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) - factory_template['schema']['properties']['variables']['properties'].each_key do |factory_variable| - variable_id = URI.encode_www_form_component("#{variable_path}/#{factory_variable}") - - @http.post( - "http://localhost:3000/secrets/#{account}/variable/#{variable_id}", - # All values must be sent to Conjur as strings - template_variables['variables'][factory_variable].to_s, - { 'Authorization' => authorization } - ) + ).bind do |body_variables| + # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. + # Conjur variables should be use dashes rather than underscores. + template_variables = body_variables.transform_keys { |key| key.to_s.underscore } + + # Render the policy from the template and provided values + policy_template = @base64.decode64(factory_template['policy']) + + # Push rendered policy to the desired policy branch + @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) + .bind do |policy_load_path| + valid_variables = factory_template['schema']['properties'].keys - ['variables'] + render_and_apply_policy( + policy_load_path: policy_load_path, + policy_template: policy_template, + variables: template_variables.select { |k,_| valid_variables.include?(k) }, + account: account, + authorization: authorization + ).bind do |result| + return @success.new(result) unless factory_template['schema']['properties'].key?('variables') + + # Set Policy Factory variables + @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) + .bind { |variable_path| + set_factory_variables( + schema_variables: factory_template['schema']['properties']['variables']['properties'], + factory_variables: template_variables['variables'], + variable_path: variable_path, + authorization: authorization, + account: account + ) + }.bind { + # If variables were added successfully, return the result so that + # we send the policy load response back to the client. + @success.new(result) + } + end + end end - end - response + + + # # Push rendered policy to the desired policy branch + # policy_post = @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) + # .bind do |policy_load_path| + # render_and_apply_policy( + # policy_load_path: policy_load_path, + # policy_template: policy_template, + # # TODO: restrict the scope to the first level (exclude variables) if present + # variables: @json.parse(params) + # ) + # end + # .bind do |result| + # return result unless factory_template['schema']['properties'].key?('variables') + + # apply_variables( + # schema_variables: factory_template['schema']['properties']['variables']['properties'], + # variable_path: @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) + # ) + # end + + # return policy_post unless policy_post.success? + + # if factory_template['schema']['properties'].key?('variables') + # variable_path = @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) + # factory_template['schema']['properties']['variables']['properties'].each_key do |factory_variable| + # variable_id = URI.encode_www_form_component("#{variable_path}/#{factory_variable}") + + # @http.post( + # "http://localhost:3000/secrets/#{account}/variable/#{variable_id}", + # # All values must be sent to Conjur as strings + # template_variables['variables'][factory_variable].to_s, + # { 'Authorization' => authorization } + # ) + # end + # end + # policy_post end end end diff --git a/app/domain/factory/factory_loader.rb b/app/domain/factory/factory_loader.rb new file mode 100644 index 0000000000..a74135f08e --- /dev/null +++ b/app/domain/factory/factory_loader.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Factory + class FactoryLoader + def initialize(success: SuccessResponse, failure: FailureResponse, resource: Resource) + @success = success + @failure = failure + @resource = resource + end + + def load(kind:, id:, account:, current_user:) + factory_resource = @resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] + if factory_resource.blank? + return @failure.new( + "Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", + status: :not_found + ) + end + + if current_user.allowed_to?(:execute, factory_resource) + if factory_resource.secret.present? + @success.new(factory_resource.secret.value) + else + @failure.new( + "Policy Factory '#{kind}/#{id}' in account '#{account}' has not been initialized", + status: :bad_request + ) + end + else + @failure.new( + "Role '#{current_user}' does not have access to Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", + status: :forbidden + ) + end + end + end +end diff --git a/app/domain/factory/render_policy.rb b/app/domain/factory/render_policy.rb deleted file mode 100644 index bfe987eb4c..0000000000 --- a/app/domain/factory/render_policy.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Factory - class RenderPolicy - def initialize(render_engine: ERB) - @render_engine = render_engine - end - - def render(template:, variables:) - @render_engine.new(template, nil, '-').result_with_hash(variables) - end - end -end diff --git a/app/domain/factory/renderer.rb b/app/domain/factory/renderer.rb new file mode 100644 index 0000000000..b5d0230065 --- /dev/null +++ b/app/domain/factory/renderer.rb @@ -0,0 +1,17 @@ +module Factory + class Renderer + def initialize(render_engine: ERB, success: SuccessResponse, failure: FailureResponse) + @render_engine = render_engine + @success = success + @failure = failure + end + + def render(template:, variables:) + @success.new(@render_engine.new(template, nil, '-').result_with_hash(variables)) + rescue StandardError => e + # Need to add tests to understand what exceptions are thrown when + # variables are missing. This may not be enough. + @failure.new(e) + end + end +end diff --git a/app/domain/responses.rb b/app/domain/responses.rb new file mode 100644 index 0000000000..05668e91c2 --- /dev/null +++ b/app/domain/responses.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +# These response objects provide a mechanism for passing more complex response +# information upstream + +# module Utilities + # Responsible for handling "successful" requests. The + # response is returned via the `.result` method. + class SuccessResponse + attr_reader :result + + def initialize(result) + @result = result + end + + def success? + true + end + + # The result of bind should always be another Response object, if the current + # response object is successful, #bind will call the next operation + def bind(&_block) + yield(result) + end + end + + # Responsible for handling "failed" requests. + # Log level and Response code are both option. + class FailureResponse + attr_reader :message, :status + + def initialize(message, level: :warn, status: :unauthorized) + @message = message + @level = level + @status = status + end + + def success? + false + end + + def level + @level.to_sym + end + + # If the current response is a failure, further attempts to bind will just + # return this response again. + def bind + self + end + end +# end diff --git a/spec/app/domain/factory/create_from_policy_factory_spec.rb b/spec/app/domain/factory/create_from_policy_factory_spec.rb index 2bce24483d..6984a14586 100644 --- a/spec/app/domain/factory/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factory/create_from_policy_factory_spec.rb @@ -6,45 +6,221 @@ let(:rest_client) { spy(RestClient) } let(:factory) { Factory::CreateFromPolicyFactory.new(http: rest_client) } - describe('.call') do - # let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)) } - context 'when request is missing attributes' do - it 'fails with error' do - expect { - factory.call( - factory_template: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)), - request_body: { 'id' => 'foo' }, - account: 'cucumber', - authorization: 'bar' - ) - }.to raise_error(RuntimeError, "The following JSON attributes are missing: 'branch'") + describe('.validate_and_transform_request') do + context 'with a simple factory' do + let(:validated) do + factory.validate_and_transform_request( + schema: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['schema'], + params: params + ) + end + context 'when request body is missing' do + let(:params) { nil } + it 'returns a failure response' do + expect(validated.success?).to be(false) + expect(validated.message).to eq("Request body must be JSON") + expect(validated.status).to eq(:bad_request) + end + end + context 'when request body is malformed JSON' do + let(:params) { '{"foo": "bar }' } + it 'returns a failure response' do + expect(validated.success?).to be(false) + expect(validated.message).to eq("Request body must be valid JSON") + expect(validated.status).to eq(:bad_request) + end + end + context 'when request body is missing keys' do + let(:params) { { id: 'foo' }.to_json } + it 'returns a failure response' do + expect(validated.success?).to be(false) + expect(validated.message).to eq([{ message: "Missing JSON key or value for: 'branch'", key: "branch" }]) + expect(validated.status).to eq(:bad_request) + end + end + context 'when request body is missing values' do + let(:params) { { id: '', branch: 'foo' }.to_json } + it 'returns a failure response' do + expect(validated.success?).to be(false) + expect(validated.message).to eq([{ message: "Missing JSON key or value for: 'id'", key: 'id' }]) + expect(validated.status).to eq(:bad_request) + end + end + context 'when request body is valid' do + let(:params) { { id: 'foo', branch: 'bar' }.to_json } + it 'returns a failure response' do + expect(validated.success?).to be(true) + validated.bind {|result| expect(result).to eq({ 'id' => 'foo', 'branch' => 'bar' }) } + end + end + end + end + + describe('.render_and_apply_policy') do + # Technically we should mock the Factory::Renderer to make this truely a unit + # test. I'm including it here to avoid needing to maintain an extra interface. + context 'The expected data is posted to the Conjur API' do + it 'loads the approprate policy' do + factory.render_and_apply_policy( + policy_load_path: 'bar', + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['policy']), + variables: { 'id' => 'foo', 'branch' => 'bar' }, + account: 'cucumber', + authorization: 'bar' + ) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}) + end + end + + context 'when response is valid' do + let(:args) do + ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}] + end + let(:response) { double(RestClient::Response, code: 201, body: 'foo') } + let(:rest_client) do + class_double(RestClient).tap do |double| + allow(double).to receive(:post).with(*args).and_return(response) + end + end + + it 'returns successfully' do + response = factory.render_and_apply_policy( + policy_load_path: 'bar', + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['policy']), + variables: { 'id' => 'foo', 'branch' => 'bar' }, + account: 'cucumber', + authorization: 'bar' + ) + expect(response.success?).to be(true) end end - context 'when request is missing nested attributes' do - it 'fails with error' do - expect { - factory.call( - factory_template: JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)), - request_body: { - 'id' => 'foo', - 'variables' => { - 'provider-uri' => 'foo', - 'client-id' => 'bar', - 'client-secret' => 'baz' - } - }, + end + + describe('.set_factory_variables') do + let(:rest_client) do + class_double(RestClient).tap do |double| + rest_client_requests.each do |request, value| + allow(double).to receive(:post).with(request, value, authorization).and_return(response) + end + end + end + let(:authorization) { { "Authorization"=>"baz" } } + let(:rest_client_requests) do + { + 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Ffoo' => 'bing', + 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Fbar' => 'bang' + } + end + context 'when role is unauthorized' do + let(:response) { double(RestClient::Response, code: 401) } + it 'returns a failure response' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '', 'bar' => '' }, + factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:unauthorized) + expect(response.message).to eq( + "Role is unauthorized to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" + ) + end + end + context 'when role lacks privilege' do + let(:response) { double(RestClient::Response, code: 403) } + it 'returns a failure response' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '', 'bar' => '' }, + factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:forbidden) + expect(response.message).to eq( + "Role lacks the privilege to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" + ) + end + end + context 'when variable is not present' do + let(:response) { double(RestClient::Response, code: 404, body: 'response') } + it 'returns a failure response' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '', 'bar' => '' }, + factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:bad_request) + expect(response.message).to eq( + "Failed to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'. Status Code: '404', Response: 'response'" + ) + end + end + context 'when request is expected to be valid' do + let(:response) { double(RestClient::Response, code: 201) } + context 'when factory includes multiple variables' do + it 'is successful' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '', 'bar' => '' }, + factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + variable_path: 'foo/bar', account: 'cucumber', - authorization: 'bar' + authorization: 'baz' ) - }.to raise_error(RuntimeError, "The following JSON attributes are missing: '/variables/claim-mapping'") + expect(response.success?).to eq(true) + end + context 'when factory includes a single variables' do + it 'is successful' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '' }, + factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(true) + end + end + context 'when factory includes a variable not present in request' do + it 'is successful' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '', 'bar' => '' }, + factory_variables: { 'foo' => 'bing' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(true) + end + end + context 'when request includes a value not present in the factory' do + it 'is successful' do + response = factory.set_factory_variables( + schema_variables: { 'foo' => '' }, + factory_variables: { 'foo' => 'bing', 'bing' => 'foo' }, + variable_path: 'foo/bar', + account: 'cucumber', + authorization: 'baz' + ) + expect(response.success?).to eq(true) + end + end end end + end + describe('.call') do context 'when policy factory is only a policy' do it 'loads the appropriate policy' do factory.call( factory_template: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)), - request_body: { 'id' => 'foo', 'branch' => 'bar' }, + request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json, account: 'cucumber', authorization: 'bar' ) @@ -53,57 +229,71 @@ end context 'when policy factory is policy and variables' do - let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)) } - before do - factory.call( - factory_template: factory_template, - request_body: { - 'id' => 'foo', - 'variables' => { - 'provider-uri' => 'foo', - 'client-id' => 'bar', - 'client-secret' => 'baz', - 'claim-mapping' => 'bing' - } - }, - account: 'cucumber', - authorization: 'bar' - ) - end - it 'loads the appropriate policy' do - expect(rest_client).to have_received(:post).with( + let(:policy_load_args) do + [ 'http://localhost:3000/policies/cucumber/policy/conjur/authn-oidc', "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n - !variable redirect-uri\n - !variable claim-mapping\n\n - !group\n id: authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice\n id: status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: [ read ]\n resource: !webservice status\n", { "Authorization"=>"bar" } - ) + ] end - it 'sets provider-id to the expected value' do - expect(rest_client).to have_received(:post).with( + let(:provider_uri_args) do + [ 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fprovider-uri', 'foo', { 'Authorization' => 'bar' } - ) + ] end - it 'sets client-id to the expected value' do - expect(rest_client).to have_received(:post).with( + let(:client_id_args) do + [ 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-id', 'bar', { 'Authorization' => 'bar' } - ) + ] end - it 'sets client-secret to the expected value' do - expect(rest_client).to have_received(:post).with( + let(:client_secret_args) do + [ 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-secret', 'baz', { 'Authorization' => 'bar' } - ) + ] end - it 'sets claim-mapping to the expected value' do - expect(rest_client).to have_received(:post).with( + let(:claim_mapping_args) do + [ 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclaim-mapping', 'bing', { 'Authorization' => 'bar' } + ] + end + let(:policy_response) { double(RestClient::Response, code: 201, body: 'foo') } + let(:variable_response) { double(RestClient::Response, code: 201) } + let(:rest_client) do + class_double(RestClient).tap do |double| + allow(double).to receive(:post).with(*policy_load_args).and_return(policy_response) + allow(double).to receive(:post).with(*provider_uri_args).and_return(variable_response) + allow(double).to receive(:post).with(*client_id_args).and_return(variable_response) + allow(double).to receive(:post).with(*client_secret_args).and_return(variable_response) + allow(double).to receive(:post).with(*claim_mapping_args).and_return(variable_response) + end + end + + let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)) } + it 'returns successfully' do + result = factory.call( + factory_template: factory_template, + request_body: { + 'id' => 'foo', + 'variables' => { + 'provider-uri' => 'foo', + 'client-id' => 'bar', + 'client-secret' => 'baz', + 'claim-mapping' => 'bing' + } + }.to_json, + account: 'cucumber', + authorization: 'bar' ) + expect(result.success?).to eq(true) + expect(result.result).to eq('foo') end end end diff --git a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb index a4cb140f50..d97d32fe34 100644 --- a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb +++ b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -require './spec/app/domain/factory/shared.rb' +require './spec/app/domain/factory/shared' RSpec.describe(Factory::Templates::Authenticators::AuthnOidc) do subject { Factory::Templates::Authenticators::AuthnOidc } diff --git a/spec/app/domain/responses_spec.rb b/spec/app/domain/responses_spec.rb new file mode 100644 index 0000000000..4129473ca5 --- /dev/null +++ b/spec/app/domain/responses_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SuccessResponse do + context 'when initialized' do + let(:success) { SuccessResponse.new('foo') } + + describe '.result' do + it 'is the message set in the initializer' do + expect(success.result).to eq('foo') + end + end + + describe '.success?' do + it 'is true' do + expect(success.success?).to be(true) + end + end + end +end + +describe FailureResponse do + context 'when initialized with only a message' do + let(:failure) { FailureResponse.new('bar') } + + describe '.message' do + it 'is the message set in the initializer' do + expect(failure.message).to eq('bar') + end + end + + describe '.level' do + it 'is at `warn` level by default' do + expect(failure.level).to eq(:warn) + end + end + + describe '.success?' do + it 'is false' do + expect(failure.success?).to be(false) + end + end + end + + context 'when initialized with all options' do + let(:message) { 'baz' } + let(:initialize_arguments) { { level: :debug, status: :forbidden } } + let(:failure) { FailureResponse.new(message, **initialize_arguments) } + + describe '.message' do + it 'is the message set in the initializer' do + expect(failure.message).to eq('baz') + end + end + + describe '.level' do + context 'when level is a symbol' do + let(:initialize_arguments) { { level: :warn, status: :forbidden } } + it 'is the level set in the initializer' do + expect(failure.level).to eq(:warn) + end + end + + context 'when level is a string' do + let(:initialize_arguments) { { level: 'warn', status: :forbidden } } + it 'is the level set in the initializer' do + expect(failure.level).to eq(:warn) + end + end + end + + describe '.status' do + context 'when set in initializer' do + it 'is the message set in the initializer' do + expect(failure.status).to eq(:forbidden) + end + end + context 'when set by default' do + let(:initialize_arguments) { {} } + it 'is the default option' do + expect(failure.status).to eq(:unauthorized) + end + end + end + + describe '.success?' do + it 'is false' do + expect(failure.success?).to be(false) + end + end + end +end From 0b86380ae284b95506589fc975467194248d3241 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 16 Mar 2023 11:51:41 -0600 Subject: [PATCH 06/42] Adds versions to the Factory Schema --- .../templates/authenticators/authn_oidc.rb | 1 + app/domain/factory/templates/base_policy.rb | 41 ++++++--------- .../factory/templates/connections/database.rb | 1 + app/domain/factory/templates/core/grant.rb | 50 +++++++++++++++++++ app/domain/factory/templates/core/group.rb | 1 + .../factory/templates/core/managed_policy.rb | 1 + app/domain/factory/templates/core/policy.rb | 1 + app/domain/factory/templates/core/user.rb | 1 + 8 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 app/domain/factory/templates/core/grant.rb diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb index 10633e0c7b..047f088287 100644 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -49,6 +49,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "conjur/authn-oidc", schema: { diff --git a/app/domain/factory/templates/base_policy.rb b/app/domain/factory/templates/base_policy.rb index 79f2d7cf28..4df3c77bd9 100644 --- a/app/domain/factory/templates/base_policy.rb +++ b/app/domain/factory/templates/base_policy.rb @@ -12,31 +12,22 @@ def policy - !policy id: factories body: - - !policy - id: core - body: - - !variable user - - !variable host - - !variable group - - !variable policy - - !variable layer - - !variable grant - - !variable permit - - !variable managed-policy - - !policy - id: authenticators - body: - - !variable authn-azure - - !variable authn-iam - - !variable authn-oidc - - !variable authn-ldap - - !variable authn-k8s - - !variable authn-gcp - - !variable authn-jwt - - !policy - id: connections - body: - - !variable database + - !policy + id: core + body: + - !variable user + - !variable group + - !variable policy + - !variable grant + - !variable managed-policy + - !policy + id: authenticators + body: + - !variable authn-oidc + - !policy + id: connections + body: + - !variable database TEMPLATE end end diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb index a06651bd06..c9c749cf26 100644 --- a/app/domain/factory/templates/connections/database.rb +++ b/app/domain/factory/templates/connections/database.rb @@ -44,6 +44,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "<%= branch %>", schema: { diff --git a/app/domain/factory/templates/core/grant.rb b/app/domain/factory/templates/core/grant.rb new file mode 100644 index 0000000000..8a5edb004d --- /dev/null +++ b/app/domain/factory/templates/core/grant.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Core + class Grant + class << self + def policy_template + <<~TEMPLATE + - !grant + member: !<%= member_resource_type %> <%= member_resource_id %> + role: !<%= role_resource_type %> <%= role_resource_id %> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Group Template", + "description": "Creates a Conjur Group", + "type": "object", + "properties": { + "id": { + "description": "Group ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this group into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the group", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/core/group.rb b/app/domain/factory/templates/core/group.rb index 84b91eb1f2..93d9a5ce5c 100644 --- a/app/domain/factory/templates/core/group.rb +++ b/app/domain/factory/templates/core/group.rb @@ -22,6 +22,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "<%= branch %>", schema: { diff --git a/app/domain/factory/templates/core/managed_policy.rb b/app/domain/factory/templates/core/managed_policy.rb index 82e138a16b..8dd594fbac 100644 --- a/app/domain/factory/templates/core/managed_policy.rb +++ b/app/domain/factory/templates/core/managed_policy.rb @@ -24,6 +24,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "<%= branch %>", schema: { diff --git a/app/domain/factory/templates/core/policy.rb b/app/domain/factory/templates/core/policy.rb index 086a31e0f0..b55dc2ecab 100644 --- a/app/domain/factory/templates/core/policy.rb +++ b/app/domain/factory/templates/core/policy.rb @@ -25,6 +25,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "<%= branch %>", schema: { diff --git a/app/domain/factory/templates/core/user.rb b/app/domain/factory/templates/core/user.rb index c74c1b70a8..7d11ab7ac3 100644 --- a/app/domain/factory/templates/core/user.rb +++ b/app/domain/factory/templates/core/user.rb @@ -22,6 +22,7 @@ def policy_template def data Base64.encode64({ + version: 1, policy: Base64.encode64(policy_template), policy_namespace: "<%= branch %>", schema: { From 5984d245568e057a6af6967a19d00ad3338234f1 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 13 Apr 2023 08:39:05 -0600 Subject: [PATCH 07/42] initial design documentation --- app/domain/factory/Readme.md | 497 ++++++++++++++++-- .../templates/authenticators/authn_oidc.rb | 12 +- .../policy-factories/factory-usage.puml | 52 ++ .../workflow-beta-activity.puml | 177 +++++++ .../factory/Readme/Factory Info Request.png | Bin 0 -> 37672 bytes out/app/domain/factory/Readme/Readme-1.png | Bin 0 -> 108711 bytes out/app/domain/factory/Readme/Readme.png | Bin 0 -> 37672 bytes .../factory/Readme/factory-create-request.png | Bin 0 -> 108711 bytes .../factory/Readme/factory-info-request.png | Bin 0 -> 37672 bytes .../factory/Readme/factory-list-request.png | Bin 0 -> 35335 bytes .../domain/factory/Readme/factory-setup.png | Bin 0 -> 21685 bytes .../domain/factory/Readme/factory-upgrade.png | Bin 0 -> 22224 bytes .../factory-usage/factory-usage.png | Bin 0 -> 90351 bytes .../workflow-beta-activity.png | Bin 0 -> 284036 bytes .../policy-factories/workflow/workflow.png | Bin 0 -> 284036 bytes 15 files changed, 704 insertions(+), 34 deletions(-) create mode 100644 design/proposals/policy-factories/factory-usage.puml create mode 100644 design/proposals/policy-factories/workflow-beta-activity.puml create mode 100644 out/app/domain/factory/Readme/Factory Info Request.png create mode 100644 out/app/domain/factory/Readme/Readme-1.png create mode 100644 out/app/domain/factory/Readme/Readme.png create mode 100644 out/app/domain/factory/Readme/factory-create-request.png create mode 100644 out/app/domain/factory/Readme/factory-info-request.png create mode 100644 out/app/domain/factory/Readme/factory-list-request.png create mode 100644 out/app/domain/factory/Readme/factory-setup.png create mode 100644 out/app/domain/factory/Readme/factory-upgrade.png create mode 100644 out/design/proposals/policy-factories/factory-usage/factory-usage.png create mode 100644 out/design/proposals/policy-factories/workflow-beta-activity/workflow-beta-activity.png create mode 100644 out/design/proposals/policy-factories/workflow/workflow.png diff --git a/app/domain/factory/Readme.md b/app/domain/factory/Readme.md index ef33e591b4..302884b04a 100644 --- a/app/domain/factory/Readme.md +++ b/app/domain/factory/Readme.md @@ -1,58 +1,489 @@ # Policy Factory -## Policy Factory Creation Requests +## Setup + +Setup will follow the following workflow: ```plantuml -@startuml +@startuml factory-setup start -:Identify Factory\nvariable based\non request params; -if (Can role load\nfactory variable?) then - :Load Factory; - :Extract Schema from Factory; - if (Parse JSON body?) then - if (Required keys missing?) then - #pink:(400) - missing keys; - kill +:Step into running container; +if ("Conjur Enterprise?") then (yes) + :Run `evoke install factories --account `; +else (no) + :Run `conjurctl install factories --account `; +endif +partition "Installation (run as `admin`)" { + :Apply Factory base policy; + :Load each Factory into its\ncorresponding versioned variable; +} +:Verify factories are available via `/factories/`; +@enduml +``` + +## Factory Upgrade + +Upgrades will follow the following workflow: + +```plantuml +@startuml factory-upgrade +start +:Step into running container; +if ("Conjur Enterprise?") then (yes) + :Run `evoke install factories --account `; +else (no) + :Run `conjurctl install factories --account `; +endif +partition "Installation (run as `admin`)" { + :Apply Factory base policy with new factory versions; + :Load each Factory into its\ncorresponding versioned variable; +} +:Verify factories are available via `/factories/`; +@enduml +``` + +## View all Policy Factories + +A role is limited to viewing the Factories they have permission (`execute`) to see. +If a role can see a factory, they will be able to see errors in mis-configured Factories. + +```plantuml +@startuml factory-list-request +start +:Identify target Factory based on request params; +:Gather factories the role is able to view; +partition "For each Factory Version" { + repeat + if ("Factory is present?") then (yes) + if ("Is Factory format is valid?") then (yes) + if ("Is Factory Schema is valid?") then (yes) + :Display Factory details and Schema; + else + #pink:[Error] Invalid Factory Schema; + endif + else + #pink:[Error] Invalid Factory Format; + endif else - if (required values empty?) then - #pink:(400) - missing values; - kill + #pink:[Error] Factory not Defined; + endif + backward: Next Factory; + repeat while (More Factories?) +} +:Return JSON Summary; +@enduml +``` + +## Policy Factory Info Requests +```plantuml +@startuml factory-info-request +(*) --> "Identify target Factory based on request params" +if "Does Factory exist?" then + --> [yes] if "Role has permission to view factory" then + --> [yes] if "Factory is present?" then + --> "Load Factory" + --> [yes] if "Factory format is valid?" then + --> [yes] if "Factory Schema is valid?" then + --> "Return Schema" + else + --> [no] "[Error] Invalid Factory Schema" + endif else - if (Policy rendered?) then - if (Policy namespace path rendered?) then - if (Policy successfully applied) then - if (Factory has variables?) then - if (Variable successfully set?) then - :(201) Return policy response; - end + --> [no] "[Error] Invalid Factory Format" + endif + else + --> [no] "[Error] Factory not Defined" + endif + else + --> [no] "[Error] Factory not Available" + endif +else + --> [no] "[Error] Factory not Found" +endif +@enduml + +``` +## Policy Factory Creation Requests + + +```plantuml +@startuml factory-create-request +(*) --> "Identify Factory variable based on request params" +if "Does factory variable exist?" then + --> [yes] if "Can role load factory?" then + --> [yes] "Load Factory" + --> [yes] if "Does factory variable have a value?" then + --> [yes] if "Factory format is valid?" then + --> [yes] if "Factory Schema is valid?" then + --> "Extract Schema from Factory Variable" + --> "Parse [POST] JSON Request body" + --> if "is JSON valid?" + --> [yes] if "Required keys present?" + --> [yes] if "Required values present?" + --> [yes] if "Policy rendered successfully?" + --> [yes] if "Policy namespace path rendered successfully?" + --> [yes] if "Policy successfully applied" + --> [yes] if "Factory has variables?" + --> [yes] if "Variables set successfully set?" + --> "Return Policy and Variable response" + ' note left + ' Response Code: 200 + ' Response: {"response": { + ' "code": 200, + ' "created_resources": [ + ' "::", + ' {":host:": {"api_key": ""}}, + ' ":variable:" + ' ] + ' }} + ' end note + --> (*) + else + --> [no] "[Error] Setting Variable(s) not Permitted" + ' note right + ' Response Code: 401 + ' Response {"error": { + ' "code": 401, + ' "error": "Role is not permitted to set the following secrets in this factory: 'secret-1', 'secret-2'", + ' "fields": [ + ' "secret-1", + ' "secret-2" + ' ] + ' }} + ' Log Level: Error + ' Log Message: Role '' is not permitted to create the following factory variables the '': 'secret-1', 'secret-2' + ' end note + endif + else + --> [no] " Policy Created Response" + ' note left + ' Response Code: 200 + ' Response: {"response": { + ' "code": 200, + ' "created_resources": [ + ' "::", + ' {":host:": {"api_key": ""}} + ' ] + ' }} + ' end note + endif + else + --> [no] "[Error] Policy Creation not Permitted" + ' note left + ' Response Code: 401 + ' Response {"error": { + ' "code": 401, + ' "error": "Role is not permitted to create a factory in this policy" + ' }} + ' Log Level: Error + ' Log Message: Role '' is not permitted to create a factory in the '' + ' end note + endif + else + --> [no] "[Error] Invalid Factory Namespace ERB" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "error": "Policy Factory Namespace Template contains invalid ERB" + ' }} + ' Log Level: Error + ' Log Message Policy Factory 'conjur/factories/core/' Namespace Template contains invalid ERB + ' end note + endif else - #pink:(401) - setting variables not permitted; - kill + --> [no] "[Error] Invalid Factory Policy ERB" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "error": "Policy Factory Policy Template contains invalid ERB" + ' }} + ' Log Level: Error + ' Log Message Policy Factory 'conjur/factories/core/' Policy Template contains invalid ERB + ' end note endif else - :(201) Return policy response; - end + --> [no] "[Error] Missing Required Values" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "The following fields are missing values: 'field-1', 'field-2'", + ' "fields": [ + ' {"field-1": { "error": "cannot be empty" }}, + ' {"field-2": { "error": "cannot be empty" }} + ' ]}} + ' Log Level: Error + ' Log Message: The following fields are missing values in the request JSON body: 'field-1', 'field-2' + ' end note endif else - #pink:(401) - policy creation not permitted; - kill + --> [no] "[Error] Missing Required Keys" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "The following fields are missing: 'field-1', 'field-2'", + ' "fields": [ + ' {"field-1": { "error": "must be present" }}, + ' {"field-2": { "error": "must be present" }} + ' ] + ' }} + ' Log Level: Error + ' Log Message: The following fields are missing from the request JSON body: 'field-1', 'field-2' + ' end note endif else - #pink:(400) - policy namespace variable(s) missing; - kill + --> [no] "[Error] Bad Request Body" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "Request JSON contains invalid syntax" + ' }} + ' Log Level: Error + ' Log Message: Request JSON contains invalid syntax + ' end note endif else - #pink:(400) - policy variable(s) missing; - kill + --> [no] "[Error] Invalid Factory Schema" endif + else + --> [no] "[Error] Invalid Factory Format" endif + else + --> [no] "[Error] Factory not Defined" + ' note left + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "resource": "conjur/factories/core/", + ' "message": "Requested Policy Factory is empty" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory Variable "conjur/factories/core/" is empty + ' end note endif else - #pink:(400) - malformed JSON; - kill + --> [no] "[Error] Factory not Available" + ' note left + ' Response Code: 403 + ' Response: {"error": { + ' "code": 403, + ' "resource": "core/", + ' "message": "Factory is not available" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory "core/" is not available + ' end note endif else - #pink:(404) - factory not available; + --> [no] "[Error] Factory not Found" + ' note left + ' Response Code: 404 + ' Response: {"error": { + ' "code": 404, + ' "resource": "conjur/factories/core/", + ' "message": "Requested Policy Factory does not exist" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory Variable "conjur/factories/core/" does not exist + ' end note +endif +@enduml +``` + +## Policy Factory Creation Requests (beta) + +```plantuml +@startuml +start +:Identify Factory\nvariable based\non request params; +if (Does factory variable exist?) then (yes) + if (Can role load factory variable?) then (yes) + if (Does factory variable have a value?) then (yes) + :Load Factory; + :Extract Schema from Factory Variable; + :Parse [POST] JSON Request body; + ' :Extract Schema from Factory; + if (Parse JSON body?) then (yes) + if (Required keys missing?) then (no) + #pink: Missing Keys; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "The following fields are missing: 'field-1', 'field-2'", + ' "fields": [ + ' {"field-1": { "error": "must be present" }}, + ' {"field-2": { "error": "must be present" }} + ' ] + ' }} + ' Log Level: Error + ' Log Message: The following fields are missing from the request JSON body: 'field-1', 'field-2' + ' end note + kill + else (yes) + if (required values empty?) then (no) + #pink: Missing Values; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "The following fields are missing values: 'field-1', 'field-2'", + ' "fields": [ + ' {"field-1": { "error": "cannot be empty" }}, + ' {"field-2": { "error": "cannot be empty" }} + ' ]}} + ' Log Level: Error + ' Log Message: The following fields are missing values in the request JSON body: 'field-1', 'field-2' + ' end note + kill + else (yes) + if (Policy rendered?) then (yes) + if (Policy namespace path rendered?) then (yes) + if (Policy successfully applied) then (yes) + if (Factory has variables?) then (yes) + if (Variable successfully set?) then (yes) + #lightgreen: Return policy response; + ' note right + ' Response Code: 200 + ' Response: {"response": { + ' "code": 200, + ' "created_resources": [ + ' "::", + ' {":host:": {"api_key": ""}}, + ' ":variable:" + ' ] + ' }} + ' end note + end + else (no) + #pink: Setting Variable(s) not Permitted; + ' note right + ' Response Code: 401 + ' Response {"error": { + ' "code": 401, + ' "error": "Role is not permitted to set the following secrets in this factory: 'secret-1', 'secret-2'", + ' "fields": [ + ' "secret-1", + ' "secret-2" + ' ] + ' }} + ' Log Level: Error + ' Log Message: Role '' is not permitted to create the following factory variables the '': 'secret-1', 'secret-2' + ' end note + kill + endif + else (no) + #lightgreen: Return policy response; + ' note right + ' Response Code: 200 + ' Response: {"response": { + ' "code": 200, + ' "created_resources": [ + ' "::", + ' {":host:": {"api_key": ""}} + ' ] + ' }} + ' end note + kill + endif + else (no) + #pink: Policy Creation not Permitted; + ' note right + ' Response Code: 401 + ' Response {"error": { + ' "code": 401, + ' "error": "Role is not permitted to create a factory in this policy" + ' }} + ' Log Level: Error + ' Log Message: Role '' is not permitted to create a factory in the '' + ' end note + kill + endif + else (no) + #pink: Invalid Policy Namespace ERB; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "error": "Policy Factory Namespace Template contains invalid ERB" + ' }} + ' Log Level: Error + ' Log Message Policy Factory 'conjur/factories/core/' Namespace Template contains invalid ERB + ' end note + kill + endif + else (no) + #pink: Invalid Policy ERB; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "error": "Policy Factory Policy Template contains invalid ERB" + ' }} + ' Log Level: Error + ' Log Message Policy Factory 'conjur/factories/core/' Policy Template contains invalid ERB + ' end note + kill + endif + endif + endif + else (no) + #pink: Malformed JSON; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "message": "Request JSON contains invalid syntax" + ' }} + ' Log Level: Error + ' Log Message: Request JSON contains invalid syntax + ' end note + kill + endif + else (no) + #pink: Factory Variable empty; + ' note right + ' Response Code: 400 + ' Response: {"error": { + ' "code": 400, + ' "resource": "conjur/factories/core/", + ' "message": "Requested Policy Factory is empty" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory Variable "conjur/factories/core/" is empty + ' end note + kill + endif + else (no) + #pink: Factory not available; + ' note right + ' Response Code: 403 + ' Response: {"error": { + ' "code": 403, + ' "resource": "core/", + ' "message": "Factory is not available" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory "core/" is not available + ' end note + kill + endif +else (no) + #pink: Factory Variable not present; + ' note right + ' Response Code: 404 + ' Response: {"error": { + ' "code": 404, + ' "resource": "conjur/factories/core/", + ' "message": "Requested Policy Factory does not exist" + ' }} + ' Log Level: Error + ' Log Message: Policy Factory Variable "conjur/factories/core/" does not exist + ' end note kill endif @enduml diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb index 047f088287..3bc6049d7f 100644 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -11,6 +11,12 @@ def policy_template <<~TEMPLATE - !policy id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> body: - !webservice @@ -49,7 +55,7 @@ def policy_template def data Base64.encode64({ - version: 1, + version: 'v1', policy: Base64.encode64(policy_template), policy_namespace: "conjur/authn-oidc", schema: { @@ -62,6 +68,10 @@ def data "description": "Service ID of the Authenticator", "type": "string" }, + "annotations": { + "description": "Additional authenticator annotations", + "type": "object" + }, "variables": { "type": "object", "properties": { diff --git a/design/proposals/policy-factories/factory-usage.puml b/design/proposals/policy-factories/factory-usage.puml new file mode 100644 index 0000000000..97f893d81d --- /dev/null +++ b/design/proposals/policy-factories/factory-usage.puml @@ -0,0 +1,52 @@ +@startuml +(*) --> "Identify Factory variable based on request params" +if "Does factory variable exist?" then + --> [yes] if "Can role load factory variable?" + --> [yes] if "Does factory variable have a value?" + --> [yes] "Load Factory" + --> "Extract Schema from Factory Variable" + --> "Parse [POST] JSON Request body" + --> if "is JSON valid?" + --> [yes] if "Required keys present?" + --> [yes] if "Required values present?" + --> [yes] if "Policy rendered successfully?" + --> [yes] if "Policy namespace path rendered successfully?" + --> [yes] if "Policy successfully applied" + --> [yes] if "Factory has variables?" + --> [yes] if "Variables set successfully set?" + --> "Return Policy and Variable response" + --> (*) + else + --> [no] "[Error] Setting Variable(s) not Permitted" + endif + else + --> [no] " Return Policy response" + endif + else + --> [no] "[Error] Policy Creation not Permitted" + endif + else + --> [no] "[Error] Invalid Policy Namespace ERB" + endif + else + --> [no] "[Error] Invalid Policy ERB" + endif + else + --> [no] "[Error] Missing Values" + endif + else + --> [no] "[Error] Missing Keys" + endif + else + --> [no] "[Error] Malformed JSON" + endif + else + --> [no] "[Error] Factory Variable empty" + endif + else + --> [no] "[Error] Factory not available" + endif +else + --> [no] "[Error] Factory Variable not present" +endif +@enduml diff --git a/design/proposals/policy-factories/workflow-beta-activity.puml b/design/proposals/policy-factories/workflow-beta-activity.puml new file mode 100644 index 0000000000..1dbbc38c12 --- /dev/null +++ b/design/proposals/policy-factories/workflow-beta-activity.puml @@ -0,0 +1,177 @@ +@startuml +(*) --> "Identify Factory variable based on request params" +if "Does factory variable exist?" then + --> [yes] if "Can role load factory variable?" + --> [yes] if "Does factory variable have a value?" + --> [yes] "Load Factory" + --> "Extract Schema from Factory Variable" + --> "Parse [POST] JSON Request body" + --> if "is JSON valid?" + --> [yes] if "Required keys present?" + --> [yes] if "Required values present?" + --> [yes] if "Policy rendered successfully?" + --> [yes] if "Policy namespace path rendered successfully?" + --> [yes] if "Policy successfully applied" + --> [yes] if "Factory has variables?" + --> [yes] if "Variables set successfully set?" + --> "Return Policy and Variable response" + note left + Response Code: 200 + Response: {"response": { + "code": 200, + "created_resources": [ + "::", + {":host:": {"api_key": ""}}, + ":variable:" + ] + }} + end note + --> (*) + else + --> [no] "[Error] Setting Variable(s) not Permitted" + note right + Response Code: 401 + Response {"error": { + "code": 401, + "error": "Role is not permitted to set the following secrets in this factory: 'secret-1', 'secret-2'", + "fields": [ + "secret-1", + "secret-2" + ] + }} + Log Level: Error + Log Message: Role '' is not permitted to create the following factory variables the '': 'secret-1', 'secret-2' + end note + endif + else + --> [no] " Return Policy response" + note left + Response Code: 200 + Response: {"response": { + "code": 200, + "created_resources": [ + "::", + {":host:": {"api_key": ""}} + ] + }} + end note + endif + else + --> [no] "[Error] Policy Creation not Permitted" + note left + Response Code: 401 + Response {"error": { + "code": 401, + "error": "Role is not permitted to create a factory in this policy" + }} + Log Level: Error + Log Message: Role '' is not permitted to create a factory in the '' + end note + endif + else + --> [no] "[Error] Invalid Policy Namespace ERB" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "error": "Policy Factory Namespace Template contains invalid ERB" + }} + Log Level: Error + Log Message Policy Factory 'conjur/factories/core/' Namespace Template contains invalid ERB + end note + endif + else + --> [no] "[Error] Invalid Policy ERB" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "error": "Policy Factory Policy Template contains invalid ERB" + }} + Log Level: Error + Log Message Policy Factory 'conjur/factories/core/' Policy Template contains invalid ERB + end note + endif + else + --> [no] "[Error] Missing Values" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "message": "The following fields are missing values: 'field-1', 'field-2'", + "fields": [ + {"field-1": { "error": "cannot be empty" }}, + {"field-2": { "error": "cannot be empty" }} + ]}} + Log Level: Error + Log Message: The following fields are missing values in the request JSON body: 'field-1', 'field-2' + end note + endif + else + --> [no] "[Error] Missing Keys" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "message": "The following fields are missing: 'field-1', 'field-2'", + "fields": [ + {"field-1": { "error": "must be present" }}, + {"field-2": { "error": "must be present" }} + ] + }} + Log Level: Error + Log Message: The following fields are missing from the request JSON body: 'field-1', 'field-2' + end note + endif + else + --> [no] "[Error] Malformed JSON" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "message": "Request JSON contains invalid syntax" + }} + Log Level: Error + Log Message: Request JSON contains invalid syntax + end note + endif + else + --> [no] "[Error] Factory Variable empty" + note left + Response Code: 400 + Response: {"error": { + "code": 400, + "resource": "conjur/factories/core/", + "message": "Requested Policy Factory is empty" + }} + Log Level: Error + Log Message: Policy Factory Variable "conjur/factories/core/" is empty + end note + endif + else + --> [no] "[Error] Factory not available" + note left + Response Code: 403 + Response: {"error": { + "code": 403, + "resource": "core/", + "message": "Factory is not available" + }} + Log Level: Error + Log Message: Policy Factory "core/" is not available + end note + endif +else + --> [no] "[Error] Factory Variable not present" + note left + Response Code: 404 + Response: {"error": { + "code": 404, + "resource": "conjur/factories/core/", + "message": "Requested Policy Factory does not exist" + }} + Log Level: Error + Log Message: Policy Factory Variable "conjur/factories/core/" does not exist + end note +endif +@enduml@enduml diff --git a/out/app/domain/factory/Readme/Factory Info Request.png b/out/app/domain/factory/Readme/Factory Info Request.png new file mode 100644 index 0000000000000000000000000000000000000000..f7fe2a99721803d7a8fbec71bb7987416c437196 GIT binary patch literal 37672 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
    PT@Zy;d>nMK+ILiZ~a-W_v;Jyefb<5sJ} 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
      PT@Zy;d>nMK+ILiZ~a-W_v;Jyefb<5sJ} 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 literal 0 HcmV?d00001 diff --git a/out/design/proposals/policy-factories/factory-usage/factory-usage.png b/out/design/proposals/policy-factories/factory-usage/factory-usage.png new file mode 100644 index 0000000000000000000000000000000000000000..584360c2fc1ec0c4793b986b4acaec0f1b7f4093 GIT binary patch literal 90351 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

      LuhpFvo>0x;8Yig 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�dGr-RH^IQ9)UEUvxt%*NWVOIVp7)^$GH-YTG$ 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 RdlG0bE+%s+^P=uw{|B@}&tw1q literal 0 HcmV?d00001 diff --git a/out/design/proposals/policy-factories/workflow-beta-activity/workflow-beta-activity.png b/out/design/proposals/policy-factories/workflow-beta-activity/workflow-beta-activity.png new file mode 100644 index 0000000000000000000000000000000000000000..b2974706e128c6e3765630dea774362299a44c2b GIT binary patch literal 284036 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
      A3cXo=7JTE-;7XPbu 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
      i=78aDo{tTOb5To1dopYf0>3OUdt^f*=sIq zhSGC$mqI^9pm#?ec0*G#Z$EI@ym{1fZNRi1I;&J#+ywYyWqmyiTsa9J<0pJf0@c#8 zy0%sawr)a(asbgtgQ^vg!5(6LYJZd*SY#@Nm)VXCr%IAkTHG}$b_ZJ~X z59EX8h;Cmql!cb|4SUH1URn40>9}ZYW6Fsv9+u=5m?OeiC`K26A!inY0spR@46thFA%-5zSpgJvsy71Sx zUHtWJK(^l+4WOB@P`6*2kTx(F0TpS}Az+$$ned(*oLpS-p#P4GV7YWROULO`HN@ zd19Xvrv486BKS~XEz}WQ7kur?E%s{;3Re$l31fSd4|;Bcc$8T)C%@0YcNZID5S?@I zgA4|Q$N&8-n=YUIn0TeOv+;ume;z#wb`Z+c2cNph|7*zwFddJnE$EpoW4iU zK@m)^CgA!LL0B7XzrGFGZ3bS8e!8_H;t~>@TU&sNY7m}nAoXxQ9gKP6K{kVkx*yGc ziMT2Y_o6FFM1(;zMnVSi57h%kn$&LJf3Nfq=7^O;JQ$&Q7Gd5aIS!|QK@)64+@Y{p zAjIdI|Gul(5Ec2D$NI#4RgPhEH1q22_Q^kvob>WO`S{7nv9bIlZD&X;(ICy7dh!oy}Q-1oHZ52&$XX0;H0m*FR_=x z)~eojcLhn`2@PGR%Lyabz{Ez`(XG|gvCE9i(_f}} z^;@fQyL%3o^Ib8*++3rj9Zm9_Z)$0&UD_C|d_2=ra4}g}N2%Oq^p=s)hfv2{THdUL($HvOwwA?yz=#of}$9QxR1Jq!<5ywi%AV1433iQ`&0;> z!cYA}U&2COS_T}_7iQO2wAUKGcdH|o+wug-TLsp0oD(vIOj~0i?BLtPF`Z#5;5{(C zR#{#kSf`NZq=hz~>CKw_qnNL?sg3`fuhPXdY+9l$e}-H?X>ICaV`$GN{+E7hmmrMf zKkV!UaN@&8*{FVyC;wo7@A3QhA5EY!>*I=woZ_6z#RG!{2KB(wxO+B+M%!mf(lzdz z@A`9HRLu=1T>Iq7I3gC}zkOSWIdsVHcNt;4(XFm;3K+`v(pJMVe0DsKAN=4C!l~g< z{3GpCqJ}e}J33CnW@)Z}4B;ffM0C;Q@Zv?q^Yw6ZG8`qu1)U?uPW9Kg7wbyczg0{Y0qZ|Pa8-GI7!5fi zlahu@%)7w4$^EwmQblbzDQ=625e7_`nebg=;G{tfUDkB{ym_qAE71IHa&i)N_>&d% zgemfe4#4Gzm;QBe`PBTFm z)7*<9UVI?9&rf-ZJi5!=UBaVB5LQ>w(qbcxBFK5+Gr;@NDKWGE(N0T<<5vl(mT@|m z7S-?XRqIMLd4oj&1o8;Nu|`XHJ2GGk4G#~4Xm;s0nbrrK;JJf?tUrcu$eba(A3c~i z2wL@DuMDahD6#~aKfZ7AbtQ$CWwMY+K!dex9=YPo2PLFV%&IuP! z$;l`j&wxMS@LZd79r4zLKLOksmM-Gff0!usKSG}L7#eRWnrgb1AU&oiAdwHccUO|r zr=xQ0o`Mb%2wlyD8FoPy)id}j_?6E;l+ohfoPu>}K;P&F-Aob7*&}vO=jP_%(bf@? z@Iiq2Ef_gV&KQ*`+-m(Ts`EW>dVsWmCZQ2wIb2ik>0y%JpEDyXOdRs8b9Hb)wS;sNBhMK1k4k)C ztU`D;^I_;^*N-Int_0J12`n-X6Tye__@Vnz7Q|3X3V9kGw?&03&cpZfC{1bCvj}0& zJ^+dunseUfv z%eeXd=cpox22&GF0(Z(*sa#$A_PvC-`LF5<32pbS9Vbf~DcL-UlN;holb?t+O`03t z{k@qdTshU>X{MX)>Z;O8<)u)nk;Q>2F6%xpocf!p!nhk~s`VAZ?yS z($9mt%R^`UIFMuL>56vS)Pa$%DygbMa++pO9K0mqt$;uppJabG%a_kp1+LwCy4fQx zI=cgo^x3msTLaJTgkGqst`2URiCd&}S)cA|`Shu!IcM@mhgh-W^PJ`SlUn_`1NEN; z^0YVoY0wX>?WqI{pCu=+S1*Ki^|olNU3L(mFOiMe*45MdTuIXw|F$fs-;v*1qd;r0 zD821@``@dK6gfer<5LFFOk|TjH~1McqeAiHD+tTIDEheVGmnYze3N3WJ%it_zXg?X zt>-#QJ@WULP0$i41CV<{?0@$dze9~M;%ryvsRT;GjO%X$kOK|t;u6jzMR;U7PQB*1 z?;kt{5b0;edMhmxwyk|Vk#lv*dQ(l;Xyj$X0z*%p{L2iyM;%dgW1mI5tAadqci5DZ zuaCMr@4dby%zo|CSCq(Fx2iX~oTQ|zqBQaDq?cSK-=bRgf{I?yJhk}aCxV%)W!6W! zc}Oi|FusOQGBN`C->sb)%ctVWrSUO)iB2W{Ba z?j-x3Q-v#NK|w*&g9sue9ys0B`|pP}9qyvLw+O3AQIW*eRnxvbQ~A>}#~W08!_(T< z)>csZDO1}FuG9-STLe9M)t?B{9bf-FFKyyUr-0=1y)>a6mxdZJmx>FCyXG{D+9~$6 z)||oY-L)SN^&2rtsm8z3`wujqA7`19stj3qlc;!Ovo~ep1BGL{CPDR|z_IMSEGlTb zh8wy3yodeDaZKqQp&PM^S~-?6c+wP!HJ$nwppfn@fC?)=<=ZQ{x6r8qp;{aU+je~1 zfE^JIyNiA~EAd_qbTk5W!JYFe7ucb-cw~3xsDAAh>*m{+Mhp*DQ=qS9Wp%a7kH0rC zy|&%Xot*_v=1=EO*}J&#PUM!@?P{nV1l>mr>qU=#rS48jI}N%#m+}M%WtgPI<*W(oZ`RJwl&? zp-%yAS0cmW^0LpuZeNMBrRTdfYdRPGR!(6Lp^3>!CKu+h>1kR8N+Q`9Zw3uVS66i( zG06w>k}n0F7`-9-QC|s9}!PE zP%^D|zfmMd2uRD#$a1|p&qc|tzO&P;V*j`EmaF}XL`R_!Cx_lSUI=9>edn*gmelqT z-|-t_)!C}qn&CpxefV$*-XsZ$2Vpd#w>|Yr<;7j?Ed|4uVC;p21}E9wn6IwBa69L1 z)A%`v-DYp`q^0NI;H{acZQGZhj?Ok}!?L`zGf%Eah@j!|Ve930x5!zF=VY(ryQ>TC zNT;}Myc$iD+td^aH4vwSeEyOkwbQ_i^xRo@3V5tcESBON9Uzn#XP0dwYLq*{Bc zk`Trz$<~6$CnA56UOCpArP@3+)PvccCz(<>(=dLm4166rAv`stdl6*MpjiOKp_>HT5XbIJTCIV`l0J2exD#c08JYFkoL*nCDJ6SBoDqr9H2{F* zE1c4M#HxuLm6@gO?1(fqDMdvW!lvX^VPWanjO?8@GG28Wk}9W93V0*7?dIVDO-^-o zZ_!X8lQ$737BAIv9bC~7k5>l@V|GTyEU>@;!V}>D-3!7Wi9+mLS1w3)3M562Xb(k z0oPD4i8?%;zcU@4&PXPd?P5m8QI(sU3mk8xWzP`?11NCrL*b23r^-hzX3s{etjVB& zWtgX(G(7BT8Ng(Es{9@dR@6TwLFa~`NeLQg)$nWUkivK{?~CH|Mg{k5EXfOmPVw`-u-QvMN=F7v^8>~$qV`EL*Nzqw~;CGguEkOjz}98 z3W_&S<3Y^$2?-@qvp`O1BqojV{rj9AoExZCsJ(Tyue~Zf(Q)vLm?ddf{-`z@F$$%1 z@#i5;wH&G2g|rdN#Pktyv_lYhLehgz``+~PkcQ)Y^TC@XP9QGA!))W{H4EU*O;2+G zwQS|tCz;((l`k*w+LE~7MCxiY0lIzr(2%;EM&Gmgch!o?Hq_KM`ug0E zs${R+W%xgjUPd0UEux@Ap+w$ll;lxWg)n#3X$xe4cpn^~-X`9&WT6QrvmT6b(g;F} zmmmgzx93h-)A@tLB4BIUP3medR#sMki`)45Ga+E(v%{2ro^aWqZGU1M8F{zNC0t*D z=fbewOVy8%OE}M8ykYW9NmwG@Q5xVl2m)rJA^|EZY?>9iD#3v+ZeyrEUNN_9#{Dd4= zXUeTMM!9gA7c4`V1)m9R#;e3oqwCn6wS$bN5S!4yE#Jt0Za;SF9FV6?DuaW`C@8QC z3(5c4T)OKA2T%unM67f71CdfLtI`I>0W1#NTS@alX2s~#<{s_g* zK4HS)(9{xQg?09)6Y((vA(J zS9|&4c@7zAfP*#mCf8CaI=oWaJtgx?6|S!6{*%jpEH^m!L*)e;T;Y za0P)n`IReIFeT=xy)PpoAc2jEi81A%q@WiNfbuD?prFoS@ucE8eihkymjwmFZmqia zX-h-|7Gx9`IA|gM&S%i#&y1l}T{+l${2cwXzdf>#2$GIU)QfY06*W*G{QxT{R<{2f zQUooa4s!;(OGu#sf7T#pQ~pa>N-S_Uw1!F#ye-&0)&XA_P>Ve{pX$NylgDGSteQG`)bb_$Rf-a$Jtkca^EG7lB2z`(!U?~rn|bakm-gc8~)@OEPYLXjR3P<((Y z_e-MSOx_&o$WlvBj|MGR00&{`;Vi_~-waO~qwyE`7bhS&{^9_KE)-jM&Dy_%>;NgV zL-P)AZ*S4f2{LzTCT+lg+{{1ELIKoq@)`D1MA6*SyYCEdfyiQ?-$$a7TQ2g6Yz$jv zRn_FwRPzx{b;Ee6AVL-DcjV{DOYn{S)CFOR6=2Iy>0+m*c<+7u)BPAz0CEJv1I&B^ z>4wVQ^%urZKEkxy)UImSzw_PSd;k6>03dM5g5pK9dGs>kqzQ%lG*Ec}7yw$L)?CP# zLocMCYG`Z(_h0raSH#>i<3P>hR=l~ry}hv!xEY|>><-ua z`cfH`JPf9wrXGg+Pw_ym&_$4Kb$+pLVc9-|6h^`8H|PkwGHB2gF3LeY5SpPxcd<;l z{%A*N2P)6m4eAnJy#mvd-I9_Ui*^7yAiyAJ8fXivz~8Jv4*Q0$9oNawo|~&PjV_&q zsf|Jb&_n~T{70><8FQyZDOLNhRbjb?owMdg#3vV;87VncZPbf^P3?)`q$V(sA7HRZ z)*qrGhxOL2iIhr^e+LWwJV(aaKXaTF61I~lA^cL8YksH7w) zCo>x4jgF6Z6`QsJSPvQGu-kYjR5_nf1KNm~qrR2)J~cLjtQ`<`U@flPd4_;j48!0M z2UgC}Vvh%`&f30%u|$mUD~}GboyMWiFhVjwn9|n88l>G^ID~ z4Fdy%MY&!mjlcfkG-Rq$&Y;(UJ}pxKi7o!^4<mg(lfsq|4<$Z@UN0C!yzj4}=-$en>5Lwb*TO4646DPoVmK!?IV7nvJ$u;V%hu zG?1JGCKeWG&YVf{Vh)NPuo^D6O|I~Rg%4{mWIaA0Ab`^e(7Nwl8q7@7 zXVAe|)>)gIp2bHShO|vgpm;P34uuVikpJ~KJ0(jGrL0Z&)P87=VedKsTpwP=A5t;{ zNKt9=Y{nk{`+If|DD*yB|7Tz?|R9Z#jvfz7T?%(_Z6~@tCEtLc{BPc z8F;>LGcp>X8r8)`JgeXA@}DXS+|v@UAfs7kmyJ5^C>nQ>yc=}~KQaI}f3`zNQoJ@7 zsj1mWUY~&;Mo=8r125vG>mX!=K)zc>M~5^|cEgf%@qJ*X>c9B%i4<+_lS$H#*ZvQZqH=sK(%PhG-n z$qW~3QjDsPucQzaz|Ab})lbWe+)q|fwbu^(5nmpikl+OjNQfmNRER~_V$7)meYbPC^S^B z%xYj;V)#jFEdnwhcTpOC0Vrkz+{v)zx#J*>_w@7(1LOdr*VrfsaTk;KcQRnF!$>c6 zpXszF8-Va+X!sgf2X=OL;KYo*(Y!fU0re^nlv;MA__;AfjzJ`WsH=dTW&3BW;N4O& z3xr_^gnLjzmq6s9ws3f0%59OmR*pOgI;u1Z4u{j11WI65jkp)5pcLTD{w7bVJa_2f ze9PJX8t!`#!oW8AGRT&l0$IDuxV41->tkw%fgZi7gcL?i91x?%?}{o zhxpQ3XGxH5MMWck=};nK2`RL{m*V#C3>&{vTt4-rY{2i0(3$^`j`SJb2QTnyzurw+66A4#*l9T zaIz%WPwKNV8UXu!6+%=EVg>0odeqm~ckvwn2TL`qeBB>j<|5z5lb0`5wLP91+wVX6NPnvITou>nfdQ@Z{E{Gs5Lg!f%Ck#jildL7 z93ehok)H6e9Dl^BT0`lw6y_I5Ur?s!m~ zh1+KT>#qp?Mw;RpJ^h!yJ|LSffQN2Op-EK}csBDq+e z_0*2W3WgM*HN-%=if??pm-vxN_fQUn65`gz4Su_yP|wMcEYR13Y8KqW`7OF% zs58+s z6S&#Nup2~=jDQCe**E}CK(7I}EF+L!LV19~x0CSz?93O#C+`OUk{T|uPX0k>nlylB zOOo>sJHVOM2kuKt+Za+%0>J?x1bChOaqMlU1K-Gpvw!0Ul8{iQTjAqgh25JScR@or zNEe{y96f?fkB*F7=~h)_6s9{NaA0@&-Z>CiJ_jh&i|j;|vLHl+NJsZ^%+Uq#@sA&o zw7b4p_8KFjIXrdrzy5R;sw)5UPitVzIs--?+NWn^v_WGWpO~1(rPQQH6Aw~_?^XEv z4Pa5#>t28jN5(ok!8HgDB&5XW_*dbjRlT%JoZ>S3lkB@ERDyRyvgE!3nv^8_SGWp_ zCmfhsihDmWx6w($M->!IH2c0agkU)&o2hwQ=f+f&^5TTPU-ny9DRD#Bc~4&8p15cH zk+uA*dNoD02R<7z+S`+@xwW1*R>}KDF*oHntvC z19F^PKw3X#e*baf$lxlQY1O$_=aKj5`X^z+XIXkIyX_Xxt9yZ;L@gBUot>c|JM<>7 z#bPMQ_wip@JB-Ubq#<>uOD)Cazw{aC$g#6dJMaYez3z8*!iab4u-Vx+k(`nnsnd&l z&E(=O$f)`4JkQ)hK%CzBxcTZIG;NMIZ*KMGEy?kg*F3)@A)&AE34+Pm%D>+DIR1@M zRr3D`PE~{k^wPZ@@MSfBi_K^bidiQ)-zj*#9RxW}RiTQhIK}ChDu0SOFPW&Q+3u`W ztfnIib6GNm>BUlIi;+Qv(KT?RoWYxH_IVrUB^qlf%82lJZIJElt(ygKa)yD<844%# zgqMruo^8=8ew(Ymto~qP@A2cg$A1*>)E~2AvX2kMDFl8N*CENP6p(lI9vb6jaJe+( z|E#{P%8P$0N^?o4ERsGmSZ_qZZ+6h`Nu|wD_seSqLfvzycBkab`VeX9f$_$v?d@hR zvNH}}o;BI_%q%$O+DXL+?*4nV9-NJ^z|+#GFNo{}K}o>F!{ZcHFR$?UI{{oyx?>zq z?JQVNpwE|mS$f0A0YwMEmfYPcpgscEk<88?uRWuMlRIRpBSfwZ?@eV>*;L%(FSFO< z7+LzUp4-_Alj8&3!hAuIY zX?U04oNMXnNq4ra|0x#V>$4w}oLt^-3U%}??^9K_N5YXBdkoo2+v>c%IexMpZqZ$< zJAj)uU_U=to$efZqP5Ht)c5fVMQLG;{MD){w0m*yn(bz%rR_hAo3GcRdWQVThdj#{ zqc_+dys0Rufak6=+OO*Cv1xPIubO3u@2HE5W^_5a$Oe|}l>(wOD+^=nlYrFC4Mr>t zCWRfxbz(&p{|M^Cj=OiIY4$F$SYlMEgMH6_9w8lilUMKS2nd##41U3L$S8>KRe7}d znzqDkd>|r&|Eck4i3tzio}0eF=p7%Z@-0Dh#HsO;d!m3eNyF1_E>j23RZdU0SC)OP z=ecFfPjo1#hD3+xoQ-;t8z#cpmvz4iSGGdqOWrV7KGKRCP)$r&{&z+O7lsaIB*|3TjiM|ZCj&E-b4|b-Cigs7cMm5e z%XMxmGZ)u3_pRy3r+-?;u<2?!y81~l$EXhYMEQZTwZV~@;^Zu*Y+%_^B;A&b(L5~h zvBJUqQwfVN&?u$wkXi#OG+gc42gplgw^*VeQ7C-9*XnrB??*fWJ?>1BPQQ6|*<@|H zixrA$Y(BuwECw*UFDbpYckc)lM7*M+F!KPG`G7K7KZT$TBLOUcqY-sG0BV&6{&aeoi;3>aSJQ7TW3WajPl z=p=i->+Pm9-5eGYn>#wL0jQ^sj?l=~)EEfi0MxbyNb&oJ+U|h$p+0Rb-F0ibt#3T` zTkJZ~LH9YFu6w0cO+x91X`X?HO>VHG!oH0$J%FmTh*ZXN|)i>(p{Z8 zyDHukZ)4|jT8Z^x>zb=bj>A9wu>Ys3;;Q+Gh|+phS-Gk8r6J8O&W8NUNljqauQlyN zN@@$nUBqj)(v?T;gFP0;7D`u8+DXP*kuy-IJbej$4M1-f25#1|%Bf>QD@vYVr8~0@2h^`u%=T`;BOO-aac4$`JL<(FC(c0uWnd6$KCAz-YD527p zNS47&B`a+Ik%i~trMz78eAR2-7#`!I+x)_-{e>Ud$%8^!z1*BNw|K86y|f=ck^GW( z_&V?k);1PV_CDKdC@mugn`DtO#xprs=Y^zY6mtrLi~jey+>(euT)Llsb`ExJ!NARO z?6~=mfagcT!tG@^nE6*%X{`AtcA*k zI88ew-?%l=H&W+fpT$P(R6ytb)!MTyx-AMqF7rN6J~TCBAk~ZvUb8#{npLt^1V>;t z$gvZlSM$#FntohbeoJny6{utor!`cTZaLc<%i}Id7w+QMVj8BzB|nkZ(t5x1WX2s2 z&Yt7FW%tfQVBL*YTCc~2QAAVq+Q34D8GhjqfDpXW6lPzJ&+jbUw8*Y7BABmr@Y98ypJzc+R0;M2{g3xi)@N;T) z6O&x+^bvZ8)#znRsVvFqQfEo@s%-@=?&rOb)e~6f`2=oT{a}ZA;dQChnd!jO>uB!Mkx|KX(W}J$ zYhj)EwXgt5UIyW}?9k7ZPItN5`D7sxvh^QbReq%Z}

      bV9~6{K!u)oit+F*mi!R5M(RJ`i8}!xys^>Jh#694HU#T1EB} z)@jx{f_<&=rDeX&UCy@R+9PNl7T0{w1(&+3X{UAS)U9mW&;qES&K&deo*Mlnn;{5g zgm(%FiPakQH@>#AnlI?V;d9y&!xgKDJEeoes;h1)T$&~?OoxOd&8Ou!ZJ&MX?z_eK zH)8uk&@hKYelK^)vVe2TkEgwHqwwSO7`|@8vE?I?|H8WJsGU? zF3ymDd1qh5yN|64SDxYLzvrFNYdeEl?1`PRM}K&-|Dy?dB=qHGeQUZ~%CrE6=~qP= z7PcoLWob@4+F1PU;38QOKgIo3tWo*Av98WmFH~@_4 z>K8u!e8T9GyZOOYc>LFV!~HvfrOy6V=={{@8L?^R-!*bsCb!SYT(F!a_taaxxp|fd z*Jcs;=dmrXMeH1aG&Or$Qn<|d^r(V+8rCA4TvGq_60L$}n$l>L()ZGgQ zh5Lt(mH)GjR#;)_9bzL?;5@3>XPBTG6g*^*)yzk0+-a6_}kj$Mm+AE}P`x z41|Z!p;868rPg=vtPkV7WHYIv^DV7CXQq35m3a*}EwsNRQ7kQ8LD)w{9vv@eYoplf z89Soq_IXIB3;fIK4$wOZU2VaV)pgtM0#Vut4^$;t_&sRAp3FVFi%crCR^ztp6~A+b zXIU9$^Gfc=(50;o4|j?#Kdaw z6}WEIInPG(XD zo@@PusC=uD?x_3n@lvBUIqIr)M&bsyZ}+ZDzZIO9Qf@8U;R#=;;~MgI4UUqX9oAcn z>GG6GH$p!;G8QW>?5!OaTW1~bHryT18~GLrqax5~0UDROD^~|OUL)UC39C7<|9iN2 zkl@4tK%XRB4aS$tDq|v!9Yp=2`$gTkoBitBAFS={0-#k{hUvxU0Kyx~CNGXl{!pkc z>%ZH$=FF-%hgly5f)Zo$m}JrpuHc7g6vbIqpT?2>B=DM2UN>cQV)tg6aaA4!UZ1_! zS^*A>!4-C`bUdTL6e_6WlVrZv-!^PEZPAoW9mD#b*5ZKVM*dm^*LB>f#1r@QED$4>nShxjtsky9XYpKY}G0WP>Iyv!P>D`?w`-s|bg8w&iDa!;|o zvAJ87Uy94h(9w}x?cTPW5t4t{SaWZxhQ z%M&B=M2o8gS6^vXb?{vKh8wDWXHCb!vD;_RL*WoW%)Pla={%RIp%$HyVLNQKwo=m> zeQ)_~{zXf)_@9O9_Lbc~%#6dItnQzfT}j%7RMGQ!HcH7y|V zw2>P|mDz>NzX{}*hm z-$EQU0aS6Cr^JvHrtC0{h|bWdCY>f+&!$-KRr*d>Rbf;W%gdh6=a|PD zX(~}C1@5Q|t*lyGxaaTc1dEhk;j4I(lM@0Y&&K7qTKQJ){EMBL<~^uB2hW*rSOedG z?y%F(l?q7=eitJt4ddHM#l}5V3rgUjOb{ilv}}nhz)hbFkF1dY+|)ETlT8ojf%D`} z@$t*tOiYknp7bq9)5uGhN>;3Nk|wOA$!p1hp~mvb`5HwA-aT_;M$j{KHqq6pBq%LO zAgV82c2v%GA-B>IXGK=%ExCVJR6t-o=-LTi&xS58*ROv&`>nLZH~4c=vZ(=z6TE4S z$*wN4SJiyJ3hQos-0{w{>wS5aE{<`K{a(U0u;#isi8;g328m684FYtE(Lj-He| zO%?oR@ZKktGiM?t{8v6 zoNS=H;I)UdW9Wrg5a5LIYeN?8cbX_af9a-rq|1ugqmU3BjVYsVl`x0D>K6Q7gllm7 zpg1FbU|uuso~tz5R9d{Njkmrs)3Fd)4xP8vkSZ z?bV>~zD~YI2~#_uR&g^>gMA#~^q;RJJN!x`UjVZ#+F#FCt;&{&Q6!;ic$?4FwtW1t zeeJ1kGNW<)SKx86`~Cf*}FZ5e%*lr~Hq|HVm3^O-#1e{2g#C?t!>haJ?u zD-`gs9}w4&@^7gsj9$8I%pJ8lpQGQ=PyPG=#Mgr2-|gTQg>Yy`2n3a<{{E;#7gjZi z|5@xTlK+Q?#|6wrmoi2kasV_b2;>9!YlYw_1yb;F?akE!33D@GAI*es06O9?zCDyn zi{!;$3AsBsI25gr@)`0$Cu^vALe=&8<+EU?S!0|L*m)&FWkrW8*=NfnULcauTJn;3*O!hr;j2qNwfEqS0 z*h+r=`W2c~SE3n>2Ck&M0_gVP??*s-$)a#j(#^CuV3YLHr%d=7e9P9~J^OM~Eyy1~ zV(uziJf!!aVRc7G$5O`pL;GB4lm<;zmjp4l5SPVkNp5uMKl)4+68LCW1OEaX1q6D4 z3Dg)LT=`!I<0)$&T;jjZ3y%o$^BWt}Fn1h0vLeEaS6PX_0FBW)B^Msj?f^Leq@h7O zWiAN_HVh+uRKiyk0goen*8&+jySf1D21i+=LmkBHY&?92e0x&uY(hc;RP!Ru0-;_` z8+DBsNS>f)0wlq$PW4a!Wi8Up(>Nsn%MdMf&IKR?J$m#A#4H4{YBnPEd4JBTJm~Z1 z`I=FGsyc&pX~Hm!W%7{Ha&tQadj$H&E=~QsnNEK8?AjM9TL8o)eV7Hi5$a@_6{BVz z7-Foiu7(B%5_C(?!tmv1j5Qq{&8}&1ad9z71P;Ggdh9(9X#DH1RKO- zZEh2?0s?2yACbqMdxGN$*Q@Rm;OECqBry<{5xh966(WOgOCEI$nBPP7y)RdbKrB5+ zhCgV_Fyg>9&Vg=T=qem7ERd&aNe~($6Twk(ez;aA9}Rw7_o3e<^eG~!eNG)f4v<^)W#>_sn1JGNmWcGc_LcoM-dw^e19A{f_TUtif2*}*1tAB z0Nu{MgFLL1l+;(QHlZt;vNnL{fuU_g47Jtae3C_Ks)@|ysT=Lyt z_iYp1uQ}w+T_?vc*#lWSLYn;@1tC#`2-<5d1M^H^%rnr$wQ9Rbz=NqWZ(R? zA5AXx;6*UNxO&YZE-ntCde@(lnuZ7`}0`dV6Jha&&YOtM0h+ z%yc0JP$ zE&$%!H-QuKKdPZdi-@YkXbigx?9XK=cSiE7W;{PmJa2fv4m&o+qNo@K2xF&TuJz3< z=zJ%Z8yoH}?qOEu(2O=mc2hbqS08@b1vLVcYGQJTjW}cXb{Bl1BeVM9D##o>2p08l zps~r3hh5y2cHh7SyPv+$tv-urK4x<2bPP@7zaFSSW`d}AcMD+apzOg+P~XG+72ow( zMQ)33yMd)jp2=A@Hi=lMZoM&ql8@?a_%+|+gtsCkF3p|ziRA?P(fd()g@g*T4!X)2 zK1N1H2*Ur;e=;Ew>i6g7Y{>?o(82H)xTYjxuKs+2f|j#_pENK7^bX&@lSJo%D^G=H zfsbt6blN%eL4g6nz=m-%Cr6ss{eaTVsu0;i9?5K3lDwg!(jH_%%A7;y3w%JK!APL4 zb0*m}g^kTkgynZA9*LsBM~AiYASr`9&|O3o^a5LV`oW?#-H0DcNwNGtY(6mz02h?9 zFagQcs{fr2uw$X#42PdDCaIvhBGC~}jJwswmN|GS*>wnV&z%7Tjb_zB^>Dre<^yO0 zb)h~%82iYBu?H@0q}O$>+02N9L9!I;i-T_r>gNFl9%rAk8R#_K*&s#j5K&jGkL>#h zU0FtE0?>DDOR^5O{$kUZTTeXnWd=>zW|}rOW720B$*$FHe1C$2_5aZ&PdTJ&8E1}u z$J6K%A2@(wwamaj8V~YltDxquL$rFOR^VYl1hj~j=H{1&!H05io&EgCjjf}se-tOSCkT`uA~4U83dLeTnTBzaiCp?j!t zxQRUw``E-wnJ=}J(=gY6Lqhor)Zg&nLv20ej|zqvia1@u1LMf{N<1#@%J3_OQH+ZdB$%)-gp+19oIVTkbi#s|cH zF|@eLQ~yEl^-KBrY^4_N#Grly)`tr*J{JS^!EeMjQUi5aJpls;Cag8mru`s|J8;hU z^8Ll3E&>gQ5MTQz648ri&(do)HvpSd(D40lFPr{3B>Songn8yxbMw zXdxvw;4DDS)O2E#jqKnTJP$M8z|=!^L#&qMI&S3qD?((Qo9ma*vBW|1j`}J86Vdh^rSW9Bo86Z=I$S!tOB&$YoisKx z)0w4OEk+s-BpgzBa!L2;^cZMB&RnToM|_d*`_vTWe+*XC5U$w!bEsnZ&!7#0{DUcq zy)J>3+Co$`N2t*2%o+9tgh>t1rc2!Xj>_8=S-npu2KXCGC9L!B8B0nG-P?F0Up}NU z0>pdQku6KiH|{~d#I~@~OwV58ftN-FHlDj6twS5}fBxd^Z16`qP`LBh>*MZgWtHs9 z@G)T>MT9+ipG$#Glm_YQTct0n^$Y1i&;C+FByj2^?@U3XWS(n)&tzuAobP@*9E z^M-1H1JpACz)0lZ4hWUaDRc?zRNw2b`?%D6{49$X#>%nHfHkoTv}$l?=-N4I8)asT zt}ga|vvB(?Ff(dPEwDLWqQUbo-}W{zU&Sf8-Iu2?3{lYF{$T8MErfcM-82AnLQeZaR{{~!sW>lWjp!`Xr5v4|wL4_Gxb?B+e`+)W0-t7Ny)K7rg}m z@yvL=0k`H3Ls0XPKfJmN1g>LV-7VLvZmi!kDLQu<*YcBA^Fo6loxYgynN?|qI{BFq zPUBYgsjvdjpxjkBrLk^aK@`%2u_#LsL1Wa6-10(sEz5jymihJJ%$n=7zHFz;X&ZhH z=LvOol9~O-TlUVrjm67_Q)BgyYe9;ScHTH-3)3eto%emH51f*9P!ECo~RHCBb0CcI{NT z8a)_CDuq$wUPh24gW1`lsC7<$I8)$7}3>a%&@L1{ityr-^Aqfr6hds}} zeO2|{^;xLpcA2YLdsEF>q**`=EhMVr{tkcPb~BgLs=xHWTGn{nHM)kRW?eEDtYx)| z*P8D)^6D&!B$0DDO?Q6T0yn+x1ub_{Hr+u?z3=*D%Wfpwr@jwAmv3`GFT^;>Mk}&L zxUJUH^=!3_w6In4a7jmjrS}_X zK%`$+#Ll|ghG5$3x2kWkhj7tI@UdHf_Gixt&oWpCB_ zlT~$+oc*<%WNQ+Jb~v2$ioO~>$KaEO32ScMj_dzkAxEs-u52Zr{A4Y~QRB)SRJ+WOxdE|&3xhg zBjLx7<7TSQydhtptYn2ufCgzPdQ(I`96{PBv^*7VPp1LiHnL-EqZh7gq)(I z(k0Mk-f|ZVI|frnnK}i{yxU;8WKmAyolCV1eiU@+M6I#bvn%g0*6c~B9?NX=_X#kH z0QZjv5AIm7_s!puwyzPHQ8#G|8vt+V0Xr_9e4DaN7a#kbPFe4o8YYpoyIh5*3lm&u zi(PL8Z*_w0>`0Yb0&G21#i-^yD>?bWO+7A?=hhu`H|ON%lxEaZ>psTwusb-j(p)N* z_db&rE>SA|sa!5rb^p0k;oh^@JhOAtJT3X9izY2=wrk6DwXY7%Xcu~E%y-Gm2xhb! z_^nUZCW6`Q(Ig6bay(~wa&?6vG3=U@Kv|iDK6AsTR)(khww6&CJ%rPc?Xt!dM?LK`Qw=0AekHgkpY3ZjeeZS=)R?yhn zyCknK=$PECADv}VXA0V1*)3WWwC|gVIX6&ob+uCJs?KRVr@7)$i${rlA zjy`QGxyixdHT~_2EHXi-s6=-BJQwmtXLa_+74I+@G~GXo3vPUF%ciqNliarToyV%v zVHuezZ%Hs2HL7edWf`F;1qjXM;FMi;D5eVcVf%)-)z)G*q;d|dO+6|Hgl3MN+DEn9 zyhokV8c>ENB_w(r&~;`WrO7x`jvHQn!IJ(si%uP)^qm4EM zeu%P@hYEX&fP=*AC4S59Livo;eI=7u!c(bVLTReD=Q;iB`QF=^Gp}bFU?;LzQ`Xx@ zXKB>6m!MZ8?W||lo%;NSGQaL}eQQe4+`8>Q=_@Wu{VX&icva7BbWER@x9@Y>?7oTt z#*<2)2A4GoUZ-|4p1rnTzVx)5jhgJE_ZrdW=&4=r&D1P-?sI!p@46?ZWkL-f>A`&b!Gul3ltx-n-8|CiyBssOx*UDlo zhRL+0)a)tn-TyhtE~N+CgZO;sNMlBlQ{^fWEr(xm+&6)?faT~%V3-3IlyXqSAp}d@ zL9k4h6VEZIw}F{CUJV|HqoW#?4h;}&nD_J15$lCoIU0Q;YL?w!J!eYRq5rt?Zn>Tr zRa9GBKE3!U>cI?|C>e139v&v~5?IyiaJ%7f-|%()-F&Z2hu?n}LD~L&-HQCY=xAQH zI&(;KJnwqE@YEG>q{930C+)oy3Tc`(+;G2ld+c{-3Yuh(nE))baSRMS=;9bZ1ScZW zwK4b=_qLd<4|Hub^0w`i+N~;M0XJ#%T94(V@XwppiwZ&OuER0oD@Vl7dI@JaPWfh2 zz3_l=+L3fYMAV-oqr~)6OMg+-KuYJ%Rv?kjvTdJ>k((e&_Q6J{)_L~C3pU>())R?3 zeNW^{YAeezyQt^J-|%XV%&AKdt%JH1+?02>T@@Ah)8xz!a^Q-Tdui73dY0oYaX16d z%7IWRQA%i$ZsfL5Ce(?>o7XDV4q8!va#fA@GF4KzlIlZ|QCGKG+J~-7|MAKiBr{5T zotsu)?&7|ov7dEP-nB2)kiGVR9|@?sL(fH*qigx>odD zg~}am1zo)t#>P^-G(%aZd-HHL?2XeH9DhUY)L7EU@znj2;leS1%Nj@_?Y=GGI4L*& zC6x7S$lyKb^NN`Sff^;{wZncggLfc;JiN~k!5NOER6YjpA*a8<>tpt#{m~YOD-(Fw zr8k>^k-GY>z}adPZV)r*p4^?St~X*6eVk0P!Jt3YwtR|wJt@S~=i0N>7%jf7J!yOB zarOEI=n(fnT#L$cF+rD@L&KMEKHaMJ8|7-Y#(GwGRDjMOSs@+Zep3vS71jL>cpYnt!w%q~^Se_K6E-e)3ObDL ztLHE>3U?6d+TB+d$jO;)`eM%#GyV0~UwgoII{q7@2bh6q!lX_DuR%Y4?St4JVGAKaO~HA&=<`D7d)_l5In?e*?vg@WKVtnGUMs zU+9B2V?IXK2k9E{5d`lkPsAH&X>?TM^RXdJE#hm5JU^=7Ot&7d!9{gH(9+hn0!KPX z6dk|bGGbbXJX~pzO$FJ9=FIa{+}tG)tK*y}dv`Piy#D|%Hsq<2Y6T1l-SFN#J@GkI zI!H=N0^WZV_e*vm`y2B3r-7guBHpTe?K`y5{TwNE5w^`2*`fQ9=k+7eXU~B8>HP5F zo1wAShzuNPplZ~fIeyJ2NJkUqL{r)mF zyU7sn3uw%ws{O@l&Vc#%`|-cuP#jvCoxOw*2mJ#nfQv~>`wB?q$AdKXd&FCSYl>*` zq6)NdA#1t1%HwiScKnWiA9n=~o72u3uqm4|slFwN1cA=PjpOeB^LQY?ST2n?fzhP7 zfmcvOL_Z|e+|CjoduW|P_BP}(rG!*32sdCnszehS8lC`C`sdGA$AfhLxLf_TfQE=j zGboE?fo9&?d_NlvjqvfoXLZ~%VOB5@Wv*HcZ>2noWjgAOA;e=0d0tmvx%&zOJ zBS;_>6>Uy7hfSVOAs{5|fIbE_%A@92ff){%wwig#{H8gVL-+^Y581 z?r%;T580OU@$z!sxB(31BCEL}i)mvOC3DyXcURj4!boV0BJXMqUzp@#x|cP8)~Ac0 z8{c}^mvS1AklfE-|um0v3xYPYl3Zmx8RQPP%&ij z)C9b|8m-J4Rr96>mIJ9!t&!>`o9nHr6?+3;9F`_G=4{G8|K;WHzp=i~=e$>3xGX)J zJR6iwqfO~GfnVgfwG)udu&_{JRK%noZBAx>BdPPN#P|=mP*jxlzS#3F?7sH{ z@ApiI2c2#t>+eiR6r`Lrv_4UJ&;(+y17DKGP})uCDYOa?C`4{n>}KK9K1bvnAOno1 zEwZcr!S1TN6cZg1BHW0lPtT zPWYV#N=%Q()gZex@^HO|1A-TngTM``w=G1SJMp@MohpwhMAkmF9ZBhZ^gq`W#_Ail$vjP*re#D7%^AuCWgsiipLQ!rg`c}QGZ&-nmu3^wyF&{{ z3(t*^88#MpPWaCI?wjq_K9ClY7Jul=`a*fFuq3uyt{&5wuL%Q=H;xmqb#8#$-GP&_ zJT>9<7}5)-nTko+dE?9U5A4_Ag7nNl`QiDuL!1j0WX+?MzEc{rwf~Ib8*bS>s=Vhs z-qtus?NgU0qIr-=f5k!K7<45yi8P&bxA`l6ETdbr z>@Hyb;wH7LN;%^LC^8p7w_dI27!NBiMx+~d_)?f{Z6F58pDs7ojmTx$`L zWHJkZPH#8wC z#z$Mg&*QCiegF~Pg!l_S1Lk$04#e%am2-?}vHkukhxyO-ARRziG_C`6B|vWfta$rq zXZrUoogWJe?{05P?Z0DQCPYqLM2H@{M*s665TCGt11&`PB_#z#0+5|?adD3~xpT+w zxVsKI#@ULW9~!%P!J&+(JRbE|)$h;ngoK2wgJ7>}vFU@w*Isb%gq$fD13Wp}e;WWF z!1P3pOsVw(q>-YB&ZI-g2ZyT0XT{@gJ$}XE4Y&LJhw202idwn6sy6(rY@a~ym6M_oT2?dz%)j{Qdw&+BtS{$y9l$Zj9?e2VaK zql6)~Omg?tyP-3KDrL6qz>5Zb`=gF9H9qbLhc&3(fvx<$v0Ez$zpNvb6-PbspAUhg zgA1rOpe}JVH#Gc>hX;PYk;lzKT$z!lYH<&gg#-9^J`H&*=UXofAdxm2eH1xWJwM*> z=f8nM8ViIQs7pmzpdSO4+o8&sSA3m!dSxOS(Qlq|{F{n8@a$@}9h%7{|utu4Y0(8s`s3h=orRLfyfLaA9I_dFKI5?oc zt7`oCrX#TA$K^tf+P(?^?uj2NSQlY3?(yuEbX)>i?_gVyefNbTC}pX?fmyt95zMDi06cH3V+kUE-7+B2|oPo2dQ zi%rcj{dE=-l6yW9-bs%VeIH1}!&3^<3Sh+=#v^&LqoV`VU%nAzS+^-5^l>E0LSdSbf<$`T1}EG$Pr&&P5O9EN-0q0 zJXC9Rc6KHLSp8X3T~4?z3U{t=xluHP_iQCCbknrgLALqX5DKd1U^*H8ou9W*mmWg| z(LOpF%Zw!!SLq>h)0AnaEi`!G@8pkTP2KyT&}%tShd(3WV(w`;P}VR!Yy|+P0ue>c zjCx9uKgs&a&N=ltVUmwengnB94kFH9Q_^o1bjO<+O_O`^aQq**8$%;w4!i$K=G&Ox zK&|p`Zl&A?rK^!_rAL42N3UcgY{(;0bwX=I-yO5DWui)v z1yQ`s8yzK9XA8>hECdQPstr-UoD4w1x5j;4%(FC0F5SN7pY?&TyR5UIFbhc#R-K9L zn}8M#q+^!5^jlER@ZPf#AZvn4A?99?a0RI)Guvi!i^cW2coe)l$(qg9=`nZwi!W)3%q*)t@DD-95-oqx6%>mg zdcSe==CR8()ivxe$wTq7HD$fIsrkx$+){&!(!Mpy)7uV^Qh+EjR?{y#o z^uD(EEKQvd^=;Q26tlH8+l-0p0e1IhT5o>5CL(rdG2f?9UPhm`is;K~&G^E!RI~(r z*?|J!-+=FJEbnMEtzK8dZjhPD>|pE03(%M4U`ly9{q4}w!s1ftB>-J7g!#CdRPM^Q zOf4>^?VZ2&KDBeipnZH`sYfcY(hT;$q$+4<{9_>@{*{JX(9Tx4^+rOGc1Q>n_OAPy z5V^#@wrDI8r(|PDbKc+ez;}6Y4+@Gww@j5;ZNQ+BAq^^;OlrS)fdZ%Nnr|W$Qcyp= zuA2EFjQiQrNHipf>!L?N-f$JrScaf{^cmq7w=6dDQsqknx2fc#9X&D&t ztuU3|)|?!_%dImAS=-#P`s~(?8yzq}1J|$o%$7HV&gLLyTD;UuxBYThK_doo!wi)M zQy~gFUfs2!f(pYW1=B9<56VS{4#)>XOVLh=UOUoAf$=E-Z_XQm^ckcjLWjJ^yDFS^ zVR;{!WyT32SBM`fD~v=0xX-y-TU*%=zFs$TWWTBL>jyu~bx7*2Z#e(xOzmY7AVIO* z`94}*orwiq2h_P&C-;_N|0fLFTpCrS3(P@>Jhz7w*p;0g3UX}5 zg+xx)OV5W343wF(y%C{VxHy-YF59PiIOB(wNh5lB#U-I8FtB-7HM>~}@+LRjvoEow zhmi`EurG7tk@Z!>8KU3aG|RjuHEzzfFAE!41EU)&fkzMAZ6Wc~kVz{6yDU^exgMRy zqIZ$t?%QK^YH8W_ut=mg&>UclTptn|Di6YDH8p@=)zY!Cb+)wu2}t!Q_@YG}pPLAd zMM%~pNY)Ei4)EJ%DoWV$iv4i&k$XcXCZ>u*BN5SYR3T~#OH>71lEC*dOj&9VYE!|^ zism2~d!@dQi{J}YsEg{D@ZjO1E%Nc>@WV_QkCX${mGzF|Bii`?(+XKbL&HQNKR^)B z=Z7u>Q1$oUe>eQT``;HqfV3(U7a*2m%jCX)nT*>Yxo~Uc)Fg!#RZoG z&mr%@PY~J(?EU)PR}{y6m20p`PfSb|QOrnc zad|UStTq;jC&aw(oKh64MD#P0UcjwE(ah)#tZ8MkGew0XR*`gQK~2d+4^ zyiX%{gvb<4IABlwnP<_vsWFwmCeVG^X~uobuqo%zi6Sj00(6 z?>f-H@Dy|I--_nCth#%vCv}x~RXhdqKVV_|Yt`V6MvYGs<@i^451$PSGoHu0pQM=6 zCqOmGe!HmxT8xADbNOfDA38yi3xctbizavCEmLA=b_(Ng&!bbG9WKp#^-P5CcC=E) zh^KXUF!sD{NxN@2gpm~%Lk0v?C3nz4&(QKi)Ν92@}paJ+_|ACEP`kz%_fRDZC2 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
      A3cXo=7JTE-;7XPbu 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
      i=78aDo{tTOb5To1dopYf0>3OUdt^f*=sIq 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Ν92@}paJ+_|ACEP`kz%_fRDZC2 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 Date: Fri, 21 Apr 2023 12:01:24 -0600 Subject: [PATCH 08/42] Additional Refactoring - Renamed `Factory` namespace to `Factories` - Refactored retrieval into a Repository --- .../policy_factories_controller.rb | 106 ++++----- .../repository/policy_factory_repository.rb | 123 +++++++++++ app/domain/{factory => factories}/Readme.md | 50 +++++ .../factories/create_from_policy_factory.rb | 165 ++++++++++++++ app/domain/{factory => factories}/renderer.rb | 2 +- .../templates/authenticators/v1/authn_oidc.rb | 112 ++++++++++ .../templates/base/v1/base_policy.rb | 44 ++++ .../templates/connections/v1/database.rb | 97 +++++++++ .../factories/templates/core/v1/grant.rb | 52 +++++ .../factories/templates/core/v1/group.rb | 57 +++++ .../templates/core/v1/managed_policy.rb | 59 +++++ .../factories/templates/core/v1/policy.rb | 65 ++++++ .../factories/templates/core/v1/user.rb | 57 +++++ .../factory/create_from_policy_factory.rb | 202 ------------------ app/domain/factory/factory_loader.rb | 37 ---- .../templates/authenticators/authn_oidc.rb | 110 ---------- app/domain/factory/templates/base_policy.rb | 36 ---- .../factory/templates/connections/database.rb | 95 -------- app/domain/factory/templates/core/grant.rb | 50 ----- app/domain/factory/templates/core/group.rb | 55 ----- .../factory/templates/core/managed_policy.rb | 57 ----- app/domain/factory/templates/core/policy.rb | 63 ------ app/domain/factory/templates/core/user.rb | 55 ----- config/routes.rb | 6 +- lib/tasks/policy_factory.rake | 24 +-- .../create_from_policy_factory_spec.rb | 16 +- .../authenticators/authn_oidc_spec.rb | 4 +- 27 files changed, 960 insertions(+), 839 deletions(-) create mode 100644 app/db/repository/policy_factory_repository.rb rename app/domain/{factory => factories}/Readme.md (94%) create mode 100644 app/domain/factories/create_from_policy_factory.rb rename app/domain/{factory => factories}/renderer.rb (96%) create mode 100644 app/domain/factories/templates/authenticators/v1/authn_oidc.rb create mode 100644 app/domain/factories/templates/base/v1/base_policy.rb create mode 100644 app/domain/factories/templates/connections/v1/database.rb create mode 100644 app/domain/factories/templates/core/v1/grant.rb create mode 100644 app/domain/factories/templates/core/v1/group.rb create mode 100644 app/domain/factories/templates/core/v1/managed_policy.rb create mode 100644 app/domain/factories/templates/core/v1/policy.rb create mode 100644 app/domain/factories/templates/core/v1/user.rb delete mode 100644 app/domain/factory/create_from_policy_factory.rb delete mode 100644 app/domain/factory/factory_loader.rb delete mode 100644 app/domain/factory/templates/authenticators/authn_oidc.rb delete mode 100644 app/domain/factory/templates/base_policy.rb delete mode 100644 app/domain/factory/templates/connections/database.rb delete mode 100644 app/domain/factory/templates/core/grant.rb delete mode 100644 app/domain/factory/templates/core/group.rb delete mode 100644 app/domain/factory/templates/core/managed_policy.rb delete mode 100644 app/domain/factory/templates/core/policy.rb delete mode 100644 app/domain/factory/templates/core/user.rb diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index f93d0809eb..214fb6205e 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -1,77 +1,77 @@ # frozen_string_literal: true -require 'base64' -require 'json' require './app/domain/responses' class PolicyFactoriesController < RestController + include AuthorizeResource + before_action :current_user def create - response = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) - .bind do |factory| - Factory::CreateFromPolicyFactory.new.call( - account: params[:account], - factory_template: JSON.parse(Base64.decode64(factory)), - request_body: request.body.read, - authorization: request.headers["Authorization"] - ) - end + response = DB::Repository::PolicyFactoryRepository.new.find( + role: current_user, + **relevant_params(%i[account kind version id]) + ).bind do |factory| + Factories::CreateFromPolicyFactory.new.call( + account: params[:account], + factory_template: factory, + request_body: request.body.read, + authorization: request.headers["Authorization"] + ) + end - if response.success? - render(json: JSON.parse(response.result), status: :created) - else - render(json: error_response(response), status: response.status) + render_response(response) do + render(json: response.result) end end - def info - factory_resource = load_factory(kind: params[:kind], id: params[:id], account: params[:account]) - authorize(:execute, factory_resource) + def show + allowed_params = %i[account kind version id] + response = DB::Repository::PolicyFactoryRepository.new.find( + role: current_user, + **relevant_params(allowed_params) + ) - template = JSON.parse(Base64.decode64(factory_resource.secret.value)) - render(json: template['schema']) + render_response(response) do + render(json: response.result.schema) + end end - private - - def error_response(response) - rtn = { - status: response.status, - body: { errors: [] } - } - if response.message.is_a?(Array) - rtn[:body][:errors] == response.message - else - rtn[:body][:errors] << { - message: response.message - } + def index + response = DB::Repository::PolicyFactoryRepository.new.find_all( + role: current_user, + account: params[:account] + ) + render_response(response) do + response_body = response.result.map do |factory| + { + name: factory.name, + namespace: factory.classification, + 'full-name': "#{factory.classification}/#{factory.name}", + 'current-version': factory.version, + description: factory.description || '' + } + end + render(json: response_body) end end - def load_factory(kind:, id:, account:) - factory_resource = Resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] - if factory_resource.blank? - return ::FailureResponse.new( - "Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", - status: :not_found - ) - end + private - if current_user.allowed_to?(:execute, factory_resource) - if factory_resource.secret.present? - ::SuccessResponse.new(factory_resource.secret.value) - else - ::FailureResponse.new( - "Policy Factory '#{kind}/#{id}' in account '#{account}' has not been initialized", - status: :bad_request - ) - end + def render_response(response, &block) + if response.success? + block.call else - ::FailureResponse.new( - "Role '#{current_user}' does not have access to Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", - status: :forbidden + render( + json: response.message.merge( + code: HTTP::Response::Status::SYMBOL_CODES[response.status] + ), + status: response.status ) end end + + def relevant_params(allowed_params) + params.permit(*allowed_params).slice(*allowed_params).to_h.symbolize_keys + end end diff --git a/app/db/repository/policy_factory_repository.rb b/app/db/repository/policy_factory_repository.rb new file mode 100644 index 0000000000..bbb6a9646a --- /dev/null +++ b/app/db/repository/policy_factory_repository.rb @@ -0,0 +1,123 @@ +require 'base64' +require 'json' + +require './app/domain/responses' + +module DB + module Repository + module DataObjects + PolicyFactory = Struct.new( + :name, + :classification, + :version, + :policy, + :policy_namespace, + :schema, + :description, + keyword_init: true + ) + end + + class PolicyFactoryRepository + def initialize( + data_object: DataObjects::PolicyFactory, + resource: ::Resource, + logger: Rails.logger + ) + @resource = resource + @data_object = data_object + @logger = logger + @success = ::SuccessResponse + @failure = ::FailureResponse + end + + def find_all(account:, role:) + factories = @resource.visible_to(role).where( + Sequel.like( + :resource_id, + "#{account}:variable:conjur/factories/%" + ) + ).all + .group_by do |item| + # form is: 'conjur/factories/core/v1/groups' + _, _, classification, _, factory = item.resource_id.split('/') + [classification, factory].join('/') + end + .map do |_, versions| + versions.max + end + .map do |factory| + response = secret_to_data_object(factory) + response.result if response.success? + end + .compact + + if factories.empty? + return @failure.new( + { message: 'Role does not have permission to use Factories' }, + status: :forbidden + ) + end + + @success.new(factories) + end + + def find(kind:, id:, account:, role:, version: nil) + factory = if version.present? + @resource["#{account}:variable:conjur/factories/#{kind}/#{version}/#{id}"] + else + @resource.where( + Sequel.like( + :resource_id, + "#{account}:variable:conjur/factories/#{kind}/%" + ) + ).all.select { |i| i.resource_id.split('/').last == id }.max + end + + if factory.present? && role.allowed_to?(:execute, factory) + return secret_to_data_object(factory) + end + + resource_id = "#{kind}/#{version || 'v1'}/#{id}" + + if factory.blank? + @failure.new( + { resource: resource_id, message: 'Requested Policy Factory does not exist' }, + status: :not_found + ) + elsif factory.secret.blank? + @failure.new( + { resource: resource_id, message: 'Requested Policy Factory is empty' }, + status: :bad_request + ) + end + end + + private + + def secret_to_data_object(variable) + factory = variable.secret&.value + if factory + _, _, classification, version, id = variable.resource_id.split('/') + decoded_factory = JSON.parse(Base64.decode64(factory)) + @success.new( + @data_object.new( + policy: Base64.decode64(decoded_factory['policy']), + policy_namespace: decoded_factory['policy_namespace'], + schema: decoded_factory['schema'], + version: version, + name: id, + classification: classification, + description: variable.annotations.find { |a| a.name == 'description' }&.value + ) + ) + else + @failure.new( + { resource: "#{classification}/#{version}/#{id}", message: 'Requested Policy Factory is not available' }, + status: :forbidden + ) + end + end + end + end +end diff --git a/app/domain/factory/Readme.md b/app/domain/factories/Readme.md similarity index 94% rename from app/domain/factory/Readme.md rename to app/domain/factories/Readme.md index 302884b04a..8ba7003c08 100644 --- a/app/domain/factory/Readme.md +++ b/app/domain/factories/Readme.md @@ -488,3 +488,53 @@ else (no) endif @enduml ``` + +### UI Workflow + +```plantuml +@startuml factory-setup +start +:Login; +:Navigate to "Policy Factories" page; +if (Can view Factories) then (yes) + :Show Factory Groupings; + :Navigate to Factory Grouping; + :Select a Factory; + if ("Can view Factory") then (yes) + :View Factory form; + if ("Factory successfully created") then (yes) + :Redirect + else + end + else + end +else (no) + :Show empty Factories page\nwith "No Factories Available"; +end +@enduml +``` + + + +## Code Architecture + +```plantuml +@startuml Basic Sample +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Component(controller, "PolicyFactoryController", "Rails", "Routes requests to Business Logic and renders results") + +Component(repository, "PolicyFactoryRepository", "Ruby", "Retrieves Factories from Conjur Variables") + +Component(data_object, "DataObjects::PolicyFactory", "Ruby") + +Component(create, "CreateFromPolicyFactory", "Ruby", "Generates Conjur elements using a Policy Factory") + +Rel(repository, controller, "loads factory from") + +' Component(repository 'PolicyFactoryRepository') + +' component PolicyFactoryController +' component PolicyFactoryRepository +@enduml +``` diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb new file mode 100644 index 0000000000..4529999454 --- /dev/null +++ b/app/domain/factories/create_from_policy_factory.rb @@ -0,0 +1,165 @@ +# frozen_string_literal: true + +require 'rest_client' +require 'json_schemer' +require 'factories/renderer' + +module Factories + class CreateFromPolicyFactory + def initialize(renderer: Factories::Renderer.new, http: RestClient, schema_validator: JSONSchemer) + @renderer = renderer + @http = http + @schema_validator = schema_validator + + # JSON, URI, and Base64 are defined here for visibility. They + # are not currently mocked in testing, thus, we're not setting + # them in the initializer. + @json = JSON + @uri = URI + + # Defined here for visibility. We shouldn't need to mock these. + @success = SuccessResponse + @failure = FailureResponse + end + + def call(factory_template:, request_body:, account:, authorization:) + validate_and_transform_request( + schema: factory_template.schema, + params: request_body + ).bind do |body_variables| + # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. + # Conjur variables should be use dashes rather than underscores. + template_variables = body_variables.transform_keys { |key| key.to_s.underscore } + + # Push rendered policy to the desired policy branch + @renderer.render(template: factory_template.policy_namespace, variables: template_variables) + .bind do |policy_load_path| + valid_variables = factory_template.schema['properties'].keys - ['variables'] + render_and_apply_policy( + policy_load_path: policy_load_path, + policy_template: factory_template.policy, + variables: template_variables.select { |k, _| valid_variables.include?(k) }, + account: account, + authorization: authorization + ).bind do |result| + return @success.new(result) unless factory_template.schema['properties'].key?('variables') + + # Set Policy Factory variables + @renderer.render(template: "#{factory_template.policy_namespace}/<%= id %>", variables: template_variables) + .bind do |variable_path| + set_factory_variables( + schema_variables: factory_template.schema['properties']['variables']['properties'], + factory_variables: template_variables['variables'], + variable_path: variable_path, + authorization: authorization, + account: account + ) + end + .bind { + # If variables were added successfully, return the result so that + # we send the policy load response back to the client. + @success.new(result) + } + end + end + end + end + + private + + def validate_and_transform_request(schema:, params:) + return @failure.new("Request body must be JSON", status: :bad_request) if params.blank? + + begin + params = @json.parse(params) + rescue + return @failure.new("Request body must be valid JSON", status: :bad_request) + end + + # Strip keys without values + params = params.select{|_, v| v.present? } + + validator = @schema_validator.schema(schema) + return @success.new(params) if validator.valid?(params) + + errors = validator.validate(params).map do |error| + case error['type'] + when 'required' + missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject(&:empty?).join('/') } #.join("', '") + missing_attributes.map do |attribute| + { + message: "Missing JSON key or value for: '#{attribute}'", + key: attribute + } + end + else + { + message: "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" + } + end + end + @failure.new(errors.flatten, status: :bad_request) + end + + def render_and_apply_policy(policy_load_path:, policy_template:, variables:, account:, authorization:) + @renderer.render( + template: policy_template, + variables: variables + ).bind do |rendered_policy| + response = @http.post( + "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", + rendered_policy, + 'Authorization' => authorization + ) + if response.code == 201 + @success.new(response.body) + else + case response.code + when 400 + @failure.new("Failed to apply generated Policy to '#{policy_load_path}'", status: :bad_request) + when 401 + @failure.new("Unauthorized to apply generated policy to '#{policy_load_path}'", status: :unauthorized) + when 403 + @failure.new("Forbidden to apply generated policy to '#{policy_load_path}'", status: :forbidden) + when 404 + @failure.new("Unable to apply generated policy to '#{policy_load_path}'", status: :not_found) + else + @failure.new( + "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", + status: :bad_request + ) + end + end + end + end + + def set_factory_variables(schema_variables:, factory_variables:, variable_path:, authorization:, account:) + schema_variables.each_key do |factory_variable| + next unless factory_variables.key?(factory_variable) + + variable_id = @uri.encode_www_form_component("#{variable_path}/#{factory_variable}") + secret_path = "secrets/#{account}/variable/#{variable_id}" + + response = @http.post( + "http://localhost:3000/#{secret_path}", + factory_variables[factory_variable].to_s, + { 'Authorization' => authorization } + ) + next if response.code == 201 + + case response.code + when 401 + return @failure.new("Role is unauthorized to set variable: '#{secret_path}'", status: :unauthorized) + when 403 + return @failure.new("Role lacks the privilege to set variable: '#{secret_path}'", status: :forbidden) + else + return @failure.new( + "Failed to set variable: '#{secret_path}'. Status Code: '#{response.code}', Response: '#{response.body}'", + status: :bad_request + ) + end + end + @success.new('Variables successfully set') + end + end +end diff --git a/app/domain/factory/renderer.rb b/app/domain/factories/renderer.rb similarity index 96% rename from app/domain/factory/renderer.rb rename to app/domain/factories/renderer.rb index b5d0230065..b7ac22765f 100644 --- a/app/domain/factory/renderer.rb +++ b/app/domain/factories/renderer.rb @@ -1,4 +1,4 @@ -module Factory +module Factories class Renderer def initialize(render_engine: ERB, success: SuccessResponse, failure: FailureResponse) @render_engine = render_engine diff --git a/app/domain/factories/templates/authenticators/v1/authn_oidc.rb b/app/domain/factories/templates/authenticators/v1/authn_oidc.rb new file mode 100644 index 0000000000..8e27db3621 --- /dev/null +++ b/app/domain/factories/templates/authenticators/v1/authn_oidc.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Authenticators + module V1 + class AuthnOidc + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + body: + - !webservice + + - !variable provider-uri + - !variable client-id + - !variable client-secret + - !variable redirect-uri + - !variable claim-mapping + + - !group + id: authenticatable + annotations: + description: Group with permission to authenticate using this authenticator + + - !permit + role: !group authenticatable + privilege: [ read, authenticate ] + resource: !webservice + + - !webservice + id: status + annotations: + description: Web service for checking authenticator status + + - !group + id: operators + annotations: + description: Group with permission to check the authenticator status + + - !permit + role: !group operators + privilege: [ read ] + resource: !webservice status + TEMPLATE + end + + def data + Base64.encode64({ + version: 'v1', + policy: Base64.encode64(policy_template), + policy_namespace: "conjur/authn-oidc", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Authn-OIDC Template", + "description": "Create a new Authn-OIDC Authenticator", + "type": "object", + "properties": { + "id": { + "description": "Service ID of the Authenticator", + "type": "string" + }, + "annotations": { + "description": "Additional authenticator annotations", + "type": "object" + }, + "variables": { + "type": "object", + "properties": { + "provider-uri": { + "description": "OIDC Provider endpoint", + "type": "string" + }, + "client-id": { + "description": "OIDC Client ID", + "type": "string" + }, + "client-secret": { + "description": "OIDC Client Secret", + "type": "string" + }, + "redirect-uri": { + "description": "Target URL to redirect to after successful authentication", + "type": "string" + }, + "claim-mapping": { + "description": "OIDC JWT claim mapping. This value must match to a Conjur Host ID.", + "type": "string" + } + }, + "required": %w[provider-uri client-id client-secret claim-mapping] + } + }, + "required": %w[id variables] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factories/templates/base/v1/base_policy.rb b/app/domain/factories/templates/base/v1/base_policy.rb new file mode 100644 index 0000000000..81a9749a78 --- /dev/null +++ b/app/domain/factories/templates/base/v1/base_policy.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Factories + module Templates + module Base + module V1 + class BasePolicy + class << self + def policy + <<~TEMPLATE + - !policy + id: conjur + body: + - !policy + id: factories + body: + - !policy + id: core + body: + - !variable + id: v1/user + annotations: + description: Create a new User + + - !variable v1/group + - !variable v1/policy + - !variable v1/grant + - !variable v1/managed-policy + + - !policy + id: authenticators + body: + - !variable v1/authn-oidc + - !policy + id: connections + body: + - !variable v1/database + TEMPLATE + end + end + end + end + end + end diff --git a/app/domain/factories/templates/connections/v1/database.rb b/app/domain/factories/templates/connections/v1/database.rb new file mode 100644 index 0000000000..5e81c85a6d --- /dev/null +++ b/app/domain/factories/templates/connections/v1/database.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Connections + module V1 + class Database + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + annotations: + factory: connections/database + body: + - &variables + - !variable url + - !variable port + - !variable username + - !variable password + + - !group consumers + - !group administrators + + # consumers can read and execute + - !permit + resource: *variables + privileges: [ read, execute ] + role: !group consumers + + # administrators can update (and read and execute, via role grant) + - !permit + resource: *variables + privileges: [ update ] + role: !group administrators + + # administrators has role consumers + - !grant + member: !group administrators + role: !group consumers + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Database Connection Template", + "description": "All information for connecting to a database", + "type": "object", + "properties": { + "id": { + "description": "Database Connection ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this database connection into", + "type": "string" + }, + "variables": { + "type": "object", + "properties": { + "url": { + "description": "Database URL", + "type": "string" + }, + "port": { + "description": "Database Port", + "type": "string" + }, + "username": { + "description": "Database Username", + "type": "string" + }, + "password": { + "description": "Database Password", + "type": "string" + }, + }, + "required": %w[url port username password] + } + }, + "required": %w[id branch variables] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factories/templates/core/v1/grant.rb b/app/domain/factories/templates/core/v1/grant.rb new file mode 100644 index 0000000000..66a7076425 --- /dev/null +++ b/app/domain/factories/templates/core/v1/grant.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Core + module V1 + class Grant + class << self + def policy_template + <<~TEMPLATE + - !grant + member: !<%= member_resource_type %> <%= member_resource_id %> + role: !<%= role_resource_type %> <%= role_resource_id %> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Group Template", + "description": "Creates a Conjur Group", + "type": "object", + "properties": { + "id": { + "description": "Group ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this group into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the group", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factories/templates/core/v1/group.rb b/app/domain/factories/templates/core/v1/group.rb new file mode 100644 index 0000000000..baa3bdbf6d --- /dev/null +++ b/app/domain/factories/templates/core/v1/group.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Core + module V1 + class Group + class << self + def policy_template + <<~TEMPLATE + - !group + id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Group Template", + "description": "Creates a Conjur Group", + "type": "object", + "properties": { + "id": { + "description": "Group ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this group into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the group", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factories/templates/core/v1/managed_policy.rb b/app/domain/factories/templates/core/v1/managed_policy.rb new file mode 100644 index 0000000000..dcc1c45364 --- /dev/null +++ b/app/domain/factories/templates/core/v1/managed_policy.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Core + module V1 + class ManagedPolicy + class << self + def policy_template + <<~TEMPLATE + - !group <%= name %>-admins + - !policy + id: <%= name %> + owner: !group <%= name %>-admins + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Managed Policy Template", + "description": "Policy with an owner group", + "type": "object", + "properties": { + "name": { + "description": "Policy name (used to create the policy ID and the -admins owner group)", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this policy into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[name branch] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factories/templates/core/v1/policy.rb b/app/domain/factories/templates/core/v1/policy.rb new file mode 100644 index 0000000000..e06dfefb85 --- /dev/null +++ b/app/domain/factories/templates/core/v1/policy.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Core + module V1 + class Policy + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + <% if defined?(owner) %> + owner: <%= owner %> + <% end %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "User Template", + "description": "Creates a Conjur Policy", + "type": "object", + "properties": { + "id": { + "description": "Policy ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this policy into", + "type": "string" + }, + "owner": { + "description": "Optional owner of this policy", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + + end + end + end +end diff --git a/app/domain/factories/templates/core/v1/user.rb b/app/domain/factories/templates/core/v1/user.rb new file mode 100644 index 0000000000..907bbf5c86 --- /dev/null +++ b/app/domain/factories/templates/core/v1/user.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'base64' + +module Factories + module Templates + module Core + module V1 + class User + class << self + def policy_template + <<~TEMPLATE + - !user + id: <%= id %> + <% if defined?(annotations) %> + annotations: + <% annotations.each do |key, value| -%> + <%= key %>: <%= value %> + <% end -%> + <% end -%> + TEMPLATE + end + + def data + Base64.encode64({ + version: 1, + policy: Base64.encode64(policy_template), + policy_namespace: "<%= branch %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "User Template", + "description": "Creates a Conjur User", + "type": "object", + "properties": { + "id": { + "description": "User ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this user into", + "type": "string" + }, + "annotations": { + "description": "Additional annotations to add to the user", + "type": "object" + } + }, + "required": %w[id branch] + } + }.to_json) + end + end + end + end + end + end +end diff --git a/app/domain/factory/create_from_policy_factory.rb b/app/domain/factory/create_from_policy_factory.rb deleted file mode 100644 index 58d9784c38..0000000000 --- a/app/domain/factory/create_from_policy_factory.rb +++ /dev/null @@ -1,202 +0,0 @@ -# frozen_string_literal: true - -require 'base64' -require 'rest_client' -require 'json_schemer' -require 'factory/renderer' - -module Factory - class CreateFromPolicyFactory - def initialize(renderer: Factory::Renderer.new, http: RestClient, schema_validator: JSONSchemer, success: SuccessResponse, failure: FailureResponse) - @renderer = renderer - @http = http - @schema_validator = schema_validator - @success = success - @failure = failure - - # JSON, URI, and Base64 are defined here for visibility. They - # are not currently mocked in testing, thus, we're not setting - # them in the initializer. - @json = JSON - @base64 = Base64 - @uri = URI - end - - def validate_and_transform_request(schema:, params:) - return @failure.new("Request body must be JSON", status: :bad_request) if params.blank? - - begin - params = @json.parse(params) - rescue - return @failure.new("Request body must be valid JSON", status: :bad_request) - end - - # Strip keys without values - params = params.select{|_, v| v.present? } - - validator = @schema_validator.schema(schema) - return @success.new(params) if validator.valid?(params) - - errors = validator.validate(params).map do |error| - case error['type'] - when 'required' - missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject(&:empty?).join('/') } #.join("', '") - missing_attributes.map do |attribute| - { - message: "Missing JSON key or value for: '#{attribute}'", - key: attribute - } - end - else - { - message: "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" - } - end - end - @failure.new(errors.flatten, status: :bad_request) - end - - def render_and_apply_policy(policy_load_path:, policy_template:, variables:, account:, authorization:) - @renderer.render( - template: policy_template, - variables: variables - ).bind do |rendered_policy| - response = @http.post( - "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", - rendered_policy, - 'Authorization' => authorization - ) - if response.code == 201 - @success.new(response.body) - else - case response.code - when 400 - @failure.new("Failed to apply generated Policy to '#{policy_load_path}'", status: :bad_request) - when 401 - @failure.new("Unauthorized to apply generated policy to '#{policy_load_path}'", status: :unauthorized) - when 403 - @failure.new("Forbidden to apply generated policy to '#{policy_load_path}'", status: :forbidden) - when 404 - @failure.new("Unable to apply generated policy to '#{policy_load_path}'", status: :not_found) - else - @failure.new( - "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", - status: :bad_request - ) - end - end - end - end - - def set_factory_variables(schema_variables:, factory_variables:, variable_path:, authorization:, account:) - schema_variables.each_key do |factory_variable| - next unless factory_variables.key?(factory_variable) - - variable_id = @uri.encode_www_form_component("#{variable_path}/#{factory_variable}") - secret_path = "secrets/#{account}/variable/#{variable_id}" - - response = @http.post( - "http://localhost:3000/#{secret_path}", - factory_variables[factory_variable].to_s, - { 'Authorization' => authorization } - ) - next if response.code == 201 - - case response.code - when 401 - return @failure.new("Role is unauthorized to set variable: '#{secret_path}'", status: :unauthorized) - when 403 - return @failure.new("Role lacks the privilege to set variable: '#{secret_path}'", status: :forbidden) - else - return @failure.new( - "Failed to set variable: '#{secret_path}'. Status Code: '#{response.code}', Response: '#{response.body}'", - status: :bad_request - ) - end - end - @success.new('Variables successfully set') - end - - def call(factory_template:, request_body:, account:, authorization:) - validate_and_transform_request( - schema: factory_template['schema'], - params: request_body - ).bind do |body_variables| - # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. - # Conjur variables should be use dashes rather than underscores. - template_variables = body_variables.transform_keys { |key| key.to_s.underscore } - - # Render the policy from the template and provided values - policy_template = @base64.decode64(factory_template['policy']) - - # Push rendered policy to the desired policy branch - @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) - .bind do |policy_load_path| - valid_variables = factory_template['schema']['properties'].keys - ['variables'] - render_and_apply_policy( - policy_load_path: policy_load_path, - policy_template: policy_template, - variables: template_variables.select { |k,_| valid_variables.include?(k) }, - account: account, - authorization: authorization - ).bind do |result| - return @success.new(result) unless factory_template['schema']['properties'].key?('variables') - - # Set Policy Factory variables - @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) - .bind { |variable_path| - set_factory_variables( - schema_variables: factory_template['schema']['properties']['variables']['properties'], - factory_variables: template_variables['variables'], - variable_path: variable_path, - authorization: authorization, - account: account - ) - }.bind { - # If variables were added successfully, return the result so that - # we send the policy load response back to the client. - @success.new(result) - } - end - end - end - - - # # Push rendered policy to the desired policy branch - # policy_post = @renderer.render(template: factory_template['policy_namespace'], variables: template_variables) - # .bind do |policy_load_path| - # render_and_apply_policy( - # policy_load_path: policy_load_path, - # policy_template: policy_template, - # # TODO: restrict the scope to the first level (exclude variables) if present - # variables: @json.parse(params) - # ) - # end - # .bind do |result| - # return result unless factory_template['schema']['properties'].key?('variables') - - # apply_variables( - # schema_variables: factory_template['schema']['properties']['variables']['properties'], - # variable_path: @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) - # ) - # end - - # return policy_post unless policy_post.success? - - # if factory_template['schema']['properties'].key?('variables') - # variable_path = @renderer.render(template: "#{factory_template['policy_namespace']}/<%= id %>", variables: template_variables) - # factory_template['schema']['properties']['variables']['properties'].each_key do |factory_variable| - # variable_id = URI.encode_www_form_component("#{variable_path}/#{factory_variable}") - - # @http.post( - # "http://localhost:3000/secrets/#{account}/variable/#{variable_id}", - # # All values must be sent to Conjur as strings - # template_variables['variables'][factory_variable].to_s, - # { 'Authorization' => authorization } - # ) - # end - # end - # policy_post - end - end -end diff --git a/app/domain/factory/factory_loader.rb b/app/domain/factory/factory_loader.rb deleted file mode 100644 index a74135f08e..0000000000 --- a/app/domain/factory/factory_loader.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -module Factory - class FactoryLoader - def initialize(success: SuccessResponse, failure: FailureResponse, resource: Resource) - @success = success - @failure = failure - @resource = resource - end - - def load(kind:, id:, account:, current_user:) - factory_resource = @resource["#{account}:variable:conjur/factories/#{kind}/#{id}"] - if factory_resource.blank? - return @failure.new( - "Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", - status: :not_found - ) - end - - if current_user.allowed_to?(:execute, factory_resource) - if factory_resource.secret.present? - @success.new(factory_resource.secret.value) - else - @failure.new( - "Policy Factory '#{kind}/#{id}' in account '#{account}' has not been initialized", - status: :bad_request - ) - end - else - @failure.new( - "Role '#{current_user}' does not have access to Policy Factory '#{kind}/#{id}' does not exist in account '#{account}'", - status: :forbidden - ) - end - end - end -end diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb deleted file mode 100644 index 3bc6049d7f..0000000000 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ /dev/null @@ -1,110 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Authenticators - class AuthnOidc - class << self - def policy_template - <<~TEMPLATE - - !policy - id: <%= id %> - <% if defined?(annotations) %> - annotations: - <% annotations.each do |key, value| -%> - <%= key %>: <%= value %> - <% end -%> - <% end -%> - body: - - !webservice - - - !variable provider-uri - - !variable client-id - - !variable client-secret - - !variable redirect-uri - - !variable claim-mapping - - - !group - id: authenticatable - annotations: - description: Group with permission to authenticate using this authenticator - - - !permit - role: !group authenticatable - privilege: [ read, authenticate ] - resource: !webservice - - - !webservice - id: status - annotations: - description: Web service for checking authenticator status - - - !group - id: operators - annotations: - description: Group with permission to check the authenticator status - - - !permit - role: !group operators - privilege: [ read ] - resource: !webservice status - TEMPLATE - end - - def data - Base64.encode64({ - version: 'v1', - policy: Base64.encode64(policy_template), - policy_namespace: "conjur/authn-oidc", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Authn-OIDC Template", - "description": "Create a new Authn-OIDC Authenticator", - "type": "object", - "properties": { - "id": { - "description": "Service ID of the Authenticator", - "type": "string" - }, - "annotations": { - "description": "Additional authenticator annotations", - "type": "object" - }, - "variables": { - "type": "object", - "properties": { - "provider-uri": { - "description": "OIDC Provider endpoint", - "type": "string" - }, - "client-id": { - "description": "OIDC Client ID", - "type": "string" - }, - "client-secret": { - "description": "OIDC Client Secret", - "type": "string" - }, - "redirect-uri": { - "description": "Target URL to redirect to after successful authentication", - "type": "string" - }, - "claim-mapping": { - "description": "OIDC JWT claim mapping. This value must match to a Conjur Host ID.", - "type": "string" - } - }, - "required": %w[provider-uri client-id client-secret claim-mapping] - } - }, - "required": %w[id variables] - } - }.to_json) - end - end - end - end - end -end diff --git a/app/domain/factory/templates/base_policy.rb b/app/domain/factory/templates/base_policy.rb deleted file mode 100644 index 4df3c77bd9..0000000000 --- a/app/domain/factory/templates/base_policy.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -module Factory - module Templates - class BasePolicy - class << self - def policy - <<~TEMPLATE - - !policy - id: conjur - body: - - !policy - id: factories - body: - - !policy - id: core - body: - - !variable user - - !variable group - - !variable policy - - !variable grant - - !variable managed-policy - - !policy - id: authenticators - body: - - !variable authn-oidc - - !policy - id: connections - body: - - !variable database - TEMPLATE - end - end - end - end -end diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb deleted file mode 100644 index c9c749cf26..0000000000 --- a/app/domain/factory/templates/connections/database.rb +++ /dev/null @@ -1,95 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Connections - class Database - class << self - def policy_template - <<~TEMPLATE - - !policy - id: <%= id %> - annotations: - factory: connections/database - body: - - &variables - - !variable url - - !variable port - - !variable username - - !variable password - - - !group consumers - - !group administrators - - # consumers can read and execute - - !permit - resource: *variables - privileges: [ read, execute ] - role: !group consumers - - # administrators can update (and read and execute, via role grant) - - !permit - resource: *variables - privileges: [ update ] - role: !group administrators - - # administrators has role consumers - - !grant - member: !group administrators - role: !group consumers - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Database Connection Template", - "description": "All information for connecting to a database", - "type": "object", - "properties": { - "id": { - "description": "Database Connection ID", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this database connection into", - "type": "string" - }, - "variables": { - "type": "object", - "properties": { - "url": { - "description": "Database URL", - "type": "string" - }, - "port": { - "description": "Database Port", - "type": "string" - }, - "username": { - "description": "Database Username", - "type": "string" - }, - "password": { - "description": "Database Password", - "type": "string" - }, - }, - "required": %w[url port username password] - } - }, - "required": %w[id branch variables] - } - }.to_json) - end - end - end - end - end -end diff --git a/app/domain/factory/templates/core/grant.rb b/app/domain/factory/templates/core/grant.rb deleted file mode 100644 index 8a5edb004d..0000000000 --- a/app/domain/factory/templates/core/grant.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Core - class Grant - class << self - def policy_template - <<~TEMPLATE - - !grant - member: !<%= member_resource_type %> <%= member_resource_id %> - role: !<%= role_resource_type %> <%= role_resource_id %> - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Group Template", - "description": "Creates a Conjur Group", - "type": "object", - "properties": { - "id": { - "description": "Group ID", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this group into", - "type": "string" - }, - "annotations": { - "description": "Additional annotations to add to the group", - "type": "object" - } - }, - "required": %w[id branch] - } - }.to_json) - end - end - end - end - end -end diff --git a/app/domain/factory/templates/core/group.rb b/app/domain/factory/templates/core/group.rb deleted file mode 100644 index 93d9a5ce5c..0000000000 --- a/app/domain/factory/templates/core/group.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Core - class Group - class << self - def policy_template - <<~TEMPLATE - - !group - id: <%= id %> - <% if defined?(annotations) %> - annotations: - <% annotations.each do |key, value| -%> - <%= key %>: <%= value %> - <% end -%> - <% end -%> - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Group Template", - "description": "Creates a Conjur Group", - "type": "object", - "properties": { - "id": { - "description": "Group ID", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this group into", - "type": "string" - }, - "annotations": { - "description": "Additional annotations to add to the group", - "type": "object" - } - }, - "required": %w[id branch] - } - }.to_json) - end - end - end - end - end -end diff --git a/app/domain/factory/templates/core/managed_policy.rb b/app/domain/factory/templates/core/managed_policy.rb deleted file mode 100644 index 8dd594fbac..0000000000 --- a/app/domain/factory/templates/core/managed_policy.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Core - class ManagedPolicy - class << self - def policy_template - <<~TEMPLATE - - !group <%= name %>-admins - - !policy - id: <%= name %> - owner: !group <%= name %>-admins - <% if defined?(annotations) %> - annotations: - <% annotations.each do |key, value| -%> - <%= key %>: <%= value %> - <% end -%> - <% end -%> - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Managed Policy Template", - "description": "Policy with an owner group", - "type": "object", - "properties": { - "name": { - "description": "Policy name (used to create the policy ID and the -admins owner group)", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this policy into", - "type": "string" - }, - "annotations": { - "description": "Additional annotations to add to the user", - "type": "object" - } - }, - "required": %w[name branch] - } - }.to_json) - end - end - end - end - end -end diff --git a/app/domain/factory/templates/core/policy.rb b/app/domain/factory/templates/core/policy.rb deleted file mode 100644 index b55dc2ecab..0000000000 --- a/app/domain/factory/templates/core/policy.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Core - class Policy - class << self - def policy_template - <<~TEMPLATE - - !policy - id: <%= id %> - <% if defined?(owner) %> - owner: <%= owner %> - <% end %> - <% if defined?(annotations) %> - annotations: - <% annotations.each do |key, value| -%> - <%= key %>: <%= value %> - <% end -%> - <% end -%> - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "User Template", - "description": "Creates a Conjur Policy", - "type": "object", - "properties": { - "id": { - "description": "Policy ID", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this policy into", - "type": "string" - }, - "owner": { - "description": "Optional owner of this policy", - "type": "string" - }, - "annotations": { - "description": "Additional annotations to add to the user", - "type": "object" - } - }, - "required": %w[id branch] - } - }.to_json) - end - end - end - - end - end -end diff --git a/app/domain/factory/templates/core/user.rb b/app/domain/factory/templates/core/user.rb deleted file mode 100644 index 7d11ab7ac3..0000000000 --- a/app/domain/factory/templates/core/user.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -require 'base64' - -module Factory - module Templates - module Core - class User - class << self - def policy_template - <<~TEMPLATE - - !user - id: <%= id %> - <% if defined?(annotations) %> - annotations: - <% annotations.each do |key, value| -%> - <%= key %>: <%= value %> - <% end -%> - <% end -%> - TEMPLATE - end - - def data - Base64.encode64({ - version: 1, - policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", - schema: { - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "User Template", - "description": "Creates a Conjur User", - "type": "object", - "properties": { - "id": { - "description": "User ID", - "type": "string" - }, - "branch": { - "description": "Policy branch to load this user into", - "type": "string" - }, - "annotations": { - "description": "Additional annotations to add to the user", - "type": "object" - } - }, - "required": %w[id branch] - } - }.to_json) - end - end - end - end - end -end diff --git a/config/routes.rb b/config/routes.rb index 61ee9ed186..702ed3277e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,8 +51,10 @@ def matches?(request) post '/authn-k8s/:service_id/inject_client_cert' => 'authenticate#k8s_inject_client_cert' end - post "/factory/:account/:kind/:id" => "policy_factories#create" - get "/factory/:account/:kind/:id" => "policy_factories#info" + # Factories + post "/factories/:account/:kind/(:version)/:id" => "policy_factories#create" + get "/factories/:account/:kind/(:version)/:id" => "policy_factories#show" + get "/factories/:account" => "policy_factories#index" get "/roles/:account/:kind/*identifier" => "roles#graph", :constraints => QueryParameterActionRecognizer.new("graph") get "/roles/:account/:kind/*identifier" => "roles#all_memberships", :constraints => QueryParameterActionRecognizer.new("all") diff --git a/lib/tasks/policy_factory.rake b/lib/tasks/policy_factory.rake index a6da1ca62c..b3079ac81b 100644 --- a/lib/tasks/policy_factory.rake +++ b/lib/tasks/policy_factory.rake @@ -1,11 +1,9 @@ # frozen_string_literal: true -require 'base64' - module Factory module Templates class ValidateTemplate - def initialize(renderer: Factory::RenderPolicy.new) + def initialize(renderer: Factories::RenderPolicy.new) @renderer = renderer end @@ -39,25 +37,25 @@ namespace :policy_factory do end task test: :environment do - tester = Factory::Templates::ValidateTemplate.new + tester = Factories::Templates::ValidateTemplate.new tester.test( - factory: Factory::Templates::Core::Group, + factory: Factories::Templates::Core::Group, template_params: { "id"=>"test-group", "branch"=>"root", "annotations"=>{ "one"=>1, "two"=>2, "test/three"=>3 } } ) tester.test( - factory: Factory::Templates::Core::Group, + factory: Factories::Templates::Core::Group, template_params: { "id"=>"test-group", "branch"=>"root" } ) end task load: :environment do - client.load_policy('root', Factory::Templates::BasePolicy.policy) - client.resource('cucumber:variable:conjur/factories/core/group').add_value(Factory::Templates::Core::Group.data) - client.resource('cucumber:variable:conjur/factories/core/managed-policy').add_value(Factory::Templates::Core::ManagedPolicy.data) - client.resource('cucumber:variable:conjur/factories/core/policy').add_value(Factory::Templates::Core::Policy.data) - client.resource('cucumber:variable:conjur/factories/core/user').add_value(Factory::Templates::Core::User.data) - client.resource('cucumber:variable:conjur/factories/authenticators/authn-oidc').add_value(Factory::Templates::Authenticators::AuthnOidc.data) - client.resource('cucumber:variable:conjur/factories/connections/database').add_value(Factory::Templates::Connections::Database.data) + client.load_policy('root', Factories::Templates::Base::V1::BasePolicy.policy) + client.resource('cucumber:variable:conjur/factories/core/v1/group').add_value(Factories::Templates::Core::V1::Group.data) + client.resource('cucumber:variable:conjur/factories/core/v1/managed-policy').add_value(Factories::Templates::Core::V1::ManagedPolicy.data) + client.resource('cucumber:variable:conjur/factories/core/v1/policy').add_value(Factories::Templates::Core::V1::Policy.data) + client.resource('cucumber:variable:conjur/factories/core/v1/user').add_value(Factories::Templates::Core::V1::User.data) + client.resource('cucumber:variable:conjur/factories/authenticators/v1/authn-oidc').add_value(Factories::Templates::Authenticators::V1::AuthnOidc.data) + client.resource('cucumber:variable:conjur/factories/connections/v1/database').add_value(Factories::Templates::Connections::V1::Database.data) end task retrieve_auth_token: :environment do diff --git a/spec/app/domain/factory/create_from_policy_factory_spec.rb b/spec/app/domain/factory/create_from_policy_factory_spec.rb index 6984a14586..ebf7e9e835 100644 --- a/spec/app/domain/factory/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factory/create_from_policy_factory_spec.rb @@ -2,15 +2,15 @@ require 'spec_helper' -RSpec.describe(Factory::CreateFromPolicyFactory) do +RSpec.describe(Factories::CreateFromPolicyFactory) do let(:rest_client) { spy(RestClient) } - let(:factory) { Factory::CreateFromPolicyFactory.new(http: rest_client) } + let(:factory) { Factories::CreateFromPolicyFactory.new(http: rest_client) } describe('.validate_and_transform_request') do context 'with a simple factory' do let(:validated) do factory.validate_and_transform_request( - schema: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['schema'], + schema: JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['schema'], params: params ) end @@ -57,13 +57,13 @@ end describe('.render_and_apply_policy') do - # Technically we should mock the Factory::Renderer to make this truely a unit + # Technically we should mock the Factories::Renderer to make this truely a unit # test. I'm including it here to avoid needing to maintain an extra interface. context 'The expected data is posted to the Conjur API' do it 'loads the approprate policy' do factory.render_and_apply_policy( policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['policy']), + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['policy']), variables: { 'id' => 'foo', 'branch' => 'bar' }, account: 'cucumber', authorization: 'bar' @@ -86,7 +86,7 @@ it 'returns successfully' do response = factory.render_and_apply_policy( policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factory::Templates::Core::User.data))['policy']), + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['policy']), variables: { 'id' => 'foo', 'branch' => 'bar' }, account: 'cucumber', authorization: 'bar' @@ -219,7 +219,7 @@ context 'when policy factory is only a policy' do it 'loads the appropriate policy' do factory.call( - factory_template: JSON.parse(Base64.decode64(Factory::Templates::Core::User.data)), + factory_template: JSON.parse(Base64.decode64(Factories::Templates::Core::User.data)), request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json, account: 'cucumber', authorization: 'bar' @@ -276,7 +276,7 @@ end end - let(:factory_template) { JSON.parse(Base64.decode64(Factory::Templates::Authenticators::AuthnOidc.data)) } + let(:factory_template) { JSON.parse(Base64.decode64(Factories::Templates::Authenticators::AuthnOidc.data)) } it 'returns successfully' do result = factory.call( factory_template: factory_template, diff --git a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb index d97d32fe34..253255aeba 100644 --- a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb +++ b/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb @@ -4,8 +4,8 @@ require './spec/app/domain/factory/shared' -RSpec.describe(Factory::Templates::Authenticators::AuthnOidc) do - subject { Factory::Templates::Authenticators::AuthnOidc } +RSpec.describe(Factories::Templates::Authenticators::AuthnOidc) do + subject { Factories::Templates::Authenticators::AuthnOidc } let(:available_properties) { %w[id variables] } let(:required_properties) { available_properties } From 040c72a8094bdce751e30508dd3632811bfc8cab Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 6 Apr 2023 16:39:07 -0400 Subject: [PATCH 09/42] Cleanup: Fix YAML lint issues --- .../dev/dev_conjur_http_proxy.template.yaml | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml b/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml index 3f7ec36e68..2ed65fb2e4 100644 --- a/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml +++ b/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -15,39 +16,39 @@ spec: app: conjur-authn-k8s spec: containers: - - image: {{ CONJUR_TEST_AUTHN_K8S_TAG }} - imagePullPolicy: Always - name: conjur - command: ["conjurctl", "server"] - env: - - name: DATABASE_URL - value: postgres://postgres@postgres:5432/postgres - - name: CONJUR_ADMIN_PASSWORD - value: admin - - name: CONJUR_ACCOUNT - value: cucumber - - name: CONJUR_DATA_KEY - value: "{{ DATA_KEY }}" - - name: RAILS_ENV - value: test - # Enable coverage tracking. - - name: REQUIRE_SIMPLECOV - value: "true" - # Sleep after generating the coverage report to keep the pod alive - # so the report can be retrieved. - - name: SIMPLECOV_SLEEP - value: "true" - - name: WEB_CONCURRENCY - value: "0" - - name: RAILS_MAX_THREADS - value: "10" - - name: CONJUR_AUTHENTICATORS - value: authn-k8s/minikube - - name: https_proxy - value: 'http://tinyproxy:8888' - volumeMounts: - - mountPath: /run/authn-local - name: authn-local + - image: {{ CONJUR_TEST_AUTHN_K8S_TAG }} + imagePullPolicy: Always + name: conjur + command: ["conjurctl", "server"] + env: + - name: DATABASE_URL + value: postgres://postgres@postgres:5432/postgres + - name: CONJUR_ADMIN_PASSWORD + value: admin + - name: CONJUR_ACCOUNT + value: cucumber + - name: CONJUR_DATA_KEY + value: "{{ DATA_KEY }}" + - name: RAILS_ENV + value: test + # Enable coverage tracking. + - name: REQUIRE_SIMPLECOV + value: "true" + # Sleep after generating the coverage report to keep the pod alive + # so the report can be retrieved. + - name: SIMPLECOV_SLEEP + value: "true" + - name: WEB_CONCURRENCY + value: "0" + - name: RAILS_MAX_THREADS + value: "10" + - name: CONJUR_AUTHENTICATORS + value: authn-k8s/minikube + - name: https_proxy + value: 'http://tinyproxy:8888' + volumeMounts: + - mountPath: /run/authn-local + name: authn-local volumes: - name: authn-local emptyDir: @@ -86,3 +87,4 @@ spec: - name: tinyproxy image: {{TINYPROXY_TAG}} imagePullPolicy: Always + From 5e15f50d6f2648af945dc080ad812192a365fb38 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 6 Apr 2023 16:39:07 -0400 Subject: [PATCH 10/42] Make robust test for HTTP proxies This ensures we detect the issue in which a http proxy is not correctly used with kube exec to inject the Conjur client certificate. --- .../dev/dev_conjur_http_proxy.template.yaml | 2 ++ .../authenticators_k8s/entrypoint.sh | 1 + .../authenticators_k8s/test_gke_entrypoint.sh | 33 +++++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml b/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml index 2ed65fb2e4..8a90518224 100644 --- a/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml +++ b/ci/test_suites/authenticators_k8s/dev/dev_conjur_http_proxy.template.yaml @@ -46,6 +46,8 @@ spec: value: authn-k8s/minikube - name: https_proxy value: 'http://tinyproxy:8888' + - name: KUBERNETES_SERVICE_HOST + value: kubernetes.default.svc volumeMounts: - mountPath: /run/authn-local name: authn-local diff --git a/ci/test_suites/authenticators_k8s/entrypoint.sh b/ci/test_suites/authenticators_k8s/entrypoint.sh index 05b8d149a7..5e2727b5b9 100755 --- a/ci/test_suites/authenticators_k8s/entrypoint.sh +++ b/ci/test_suites/authenticators_k8s/entrypoint.sh @@ -155,6 +155,7 @@ function test_gke() { -e INVENTORY_TAG \ -e INVENTORY_BASE_TAG \ -e NGINX_TAG \ + -e TINYPROXY_TAG \ -e CONJUR_AUTHN_K8S_TEST_NAMESPACE \ -e USE_GKE_GCLOUD_AUTH_PLUGIN=True \ -e GCLOUD_CLUSTER_NAME \ diff --git a/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh b/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh index 6dcaef7db3..a8b65168e6 100755 --- a/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh +++ b/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh @@ -146,6 +146,7 @@ function createNamespace() { fi kubectl create namespace "$CONJUR_AUTHN_K8S_TEST_NAMESPACE" + kubectl config set-context \ "$(kubectl config current-context)" \ "--namespace=$CONJUR_AUTHN_K8S_TEST_NAMESPACE" @@ -165,6 +166,7 @@ function pushDockerImages() { docker push "$INVENTORY_TAG" docker push "$INVENTORY_BASE_TAG" docker push "$NGINX_TAG" + docker push "$TINYPROXY_TAG" } function launchConjurMaster() { @@ -251,22 +253,34 @@ function runTests() { cucumber_tags_arg="--tags \"$CUCUMBER_FILTER_TAGS\"" fi + # Run standard k8s authenticator tests run_cucumber "--tags 'not @skip' --tags 'not @k8s_skip' --tags 'not @sni_fails' --tags 'not @sni_success' $cucumber_tags_arg" + + # Run k8s authenticator tests with an HTTP proxy + run_conjur_master "dev_conjur_http_proxy" --disable-k8s-api-dns + run_cucumber "--tags 'not @skip' --tags 'not @k8s_skip' --tags '@http_proxy'" } retrieve_pod() { - kubectl get pods -l "app=$1" -o=jsonpath='{.items[].metadata.name}' + # Return the most recent pod name + kubectl get pods \ + -l "app=$1" \ + --field-selector=status.phase!=Terminating \ + --sort-by=.metadata.creationTimestamp \ + --no-headers | + tail -n 1 | + awk '{print $1}' } function run_conjur_master() { - filename=$1 + filename=$1; shift sed -e "s#{{ CONJUR_AUTHN_K8S_TAG }}#$CONJUR_AUTHN_K8S_TAG#g" "dev/$filename.${TEMPLATE_TAG}yaml" | sed -e "s#{{ CONJUR_TEST_AUTHN_K8S_TAG }}#$CONJUR_TEST_AUTHN_K8S_TAG#g" | sed -e "s#{{ NGINX_TAG }}#$NGINX_TAG#g" | sed -e "s#{{ DATA_KEY }}#$DATA_KEY#g" | sed -e "s#{{ CONJUR_AUTHN_K8S_TEST_NAMESPACE }}#$CONJUR_AUTHN_K8S_TEST_NAMESPACE#g" | - kubectl create -f - + kubectl apply -f - # Turn off -e since we expect failures when retrieving pod before it's ready. set +e @@ -301,6 +315,19 @@ function run_conjur_master() { local wait_command="while ! curl --silent --head --fail \ localhost:80 > /dev/null; do sleep 1; done" kubectl exec "$conjur_pod" -- bash -c "$wait_command" + + # Handle flags + while [[ $# -gt 0 ]]; do + case "$1" in + --disable-k8s-api-dns) + # Add a host entry to blackhole the kubernetes API endpoint + kubectl exec "$conjur_pod" -- \ + bash -c "echo '0.0.0.0 kubernetes.default.svc' >> /etc/hosts" + shift ;; + *) + echo "Unknown option: $1" + esac + done } function run_cucumber() { From 2047636444338a2a154ce008ecbd674687fa1568 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 4 Apr 2023 12:30:44 -0400 Subject: [PATCH 11/42] Add HTTP proxy support to k8s websocket --- CHANGELOG.md | 5 + .../authn_k8s/execute_command_in_container.rb | 6 +- .../authn_k8s/proxied_tcp_socket.rb | 121 +++++++++ .../authn_k8s/secure_tcp_socket.rb | 70 ++++++ .../authn_k8s/web_socket_client.rb | 230 ++++++++++++------ .../authn_k8s/proxied_tcp_socket_spec.rb | 105 ++++++++ ...spec_spec.rb => web_socket_client_spec.rb} | 21 +- 7 files changed, 463 insertions(+), 95 deletions(-) create mode 100644 app/domain/authentication/authn_k8s/proxied_tcp_socket.rb create mode 100644 app/domain/authentication/authn_k8s/secure_tcp_socket.rb create mode 100644 spec/app/domain/authentication/authn_k8s/proxied_tcp_socket_spec.rb rename spec/app/domain/authentication/authn_k8s/{web_socket_client_spec_spec.rb => web_socket_client_spec.rb} (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1410f7e347..57c7c74395 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. privilege. [cyberark/conjur#2755](https://github.com/cyberark/conjur/pull/2755) +### Fixed +- Incomplete HTTP proxy support in the Kubernetes Authenticator is fixed. This + allows for an HTTP proxy between Conjur and the Kubernetes API. + [cyberark/conjur#2766](https://github.com/cyberark/conjur/pull/2766) + ## [1.19.2] - 2023-02-01 ### Added diff --git a/app/domain/authentication/authn_k8s/execute_command_in_container.rb b/app/domain/authentication/authn_k8s/execute_command_in_container.rb index 958f13d2f4..3452a2afaf 100644 --- a/app/domain/authentication/authn_k8s/execute_command_in_container.rb +++ b/app/domain/authentication/authn_k8s/execute_command_in_container.rb @@ -45,10 +45,8 @@ def init_ws_client def ws_client @ws_client ||= @websocket_client.connect( ws_exec_url, - { - headers: headers, - cert_store: @k8s_object_lookup.cert_store - } + headers: headers, + cert_store: @k8s_object_lookup.cert_store ) end diff --git a/app/domain/authentication/authn_k8s/proxied_tcp_socket.rb b/app/domain/authentication/authn_k8s/proxied_tcp_socket.rb new file mode 100644 index 0000000000..00036add99 --- /dev/null +++ b/app/domain/authentication/authn_k8s/proxied_tcp_socket.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +require 'delegate' +require 'socket' + +module Authentication + module AuthnK8s + # A proxy socket first establishes a TCP connection through a configured + # proxy server + # + # :reek:TooManyInstanceVariables + # :reek:InstanceVariableAssumption for @proxy_socket + class ProxiedTcpSocket < SimpleDelegator + attr_reader :tcp_socket + + def initialize( + proxy_uri:, + destination_host:, + destination_port:, + timeout: 60, # seconds + + # Injected dependencies + logger: Rails.logger + ) + @proxy_uri = proxy_uri + @destination_host = destination_host + @destination_port = destination_port + @timeout = timeout + @logger = logger + + @tcp_socket = connect_proxy_socket + + # Connect to the proxy + super(@tcp_socket) + end + + protected + + def connect_proxy_socket + # We log the proxy host and port specifically because the full URI may + # contain authorization fields. + @logger.debug( + "Connecting to '#{@destination_host}:#{@destination_port}' " \ + "through proxy server: '#{@proxy_uri.host}:#{@proxy_uri.port}'" + ) + + @proxy_socket = TCPSocket.new( + @proxy_uri.host, + @proxy_uri.port, + connect_timeout: @timeout + ) + + # Send proxy connection handshake + @proxy_socket.write(proxy_connect_string) + + # This will block until the response is received. It raises an + # exception if the proxy response is not received or is invalid. + wait_for_proxy_response + + @proxy_socket + end + + # :reek:DuplicateMethodCall for @proxy_uri methods + def wait_for_proxy_response + # Set the deadline time for the socket response. + deadline = Time.now + @timeout + + # Loop until the expected string is received or the deadline is reached. + response = '' + while !response.include?("\r\n\r\n") && Time.now < deadline + # Calculate the remaining time until the deadline. + remaining_time = deadline - Time.now + + # Wait until the socket is ready to be read, or until the + # deadline is reached. + ready = IO.select([@proxy_socket], nil, nil, remaining_time) + + unless ready + # The deadline has been reached without receiving the + # expected string + raise "Timed out waiting for the proxy " \ + "('#{@proxy_uri.host}:#{@proxy_uri.port}') to respond. " \ + "Received: '#{response.strip}'" + end + + # Read from the socket and append to the response string + response += @proxy_socket.read(1) + end + + # Verify we received a valid connection response + return if response.downcase.include?('200 connection established') + + # If we didn't receive the expected response, raise an error + raise "Proxy ('#{@proxy_uri.host}:#{@proxy_uri.port}') returned an " \ + "invalid response: '#{response.strip}'" + end + + # For spec details, see: + # https://httpwg.org/specs/rfc9110.html#CONNECT + def proxy_connect_string + connect_string = \ + "CONNECT #{@destination_host}:#{@destination_port} HTTP/1.1\r\n" \ + "Host: #{@destination_host}\r\n" + + if proxy_authorization + connect_string += \ + "Proxy-Authorization: Basic #{proxy_authorization}\r\n" + end + + connect_string + "\r\n" + end + + # :reek:DuplicateMethodCall because of accessing #user and #password twice + def proxy_authorization + return unless @proxy_uri.user && @proxy_uri.password + + Base64.strict_encode64("#{@proxy_uri.user}:#{@proxy_uri.password}") + end + end + end +end diff --git a/app/domain/authentication/authn_k8s/secure_tcp_socket.rb b/app/domain/authentication/authn_k8s/secure_tcp_socket.rb new file mode 100644 index 0000000000..287376358a --- /dev/null +++ b/app/domain/authentication/authn_k8s/secure_tcp_socket.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'delegate' +require 'openssl' + +module Authentication + module AuthnK8s + # A secure socket wraps an existing TCP socket and establishes a secure + # TLS context with it. + # + # :reek:TooManyInstanceVariables + class SecureTcpSocket < SimpleDelegator + def self.default_cert_store + OpenSSL::X509::Store.new.tap(&:set_default_paths) + end + + def initialize( + socket:, + + # Optional keyword arguments to configure the TLS behavior + hostname: nil, + headers: nil, + cert_store: SecureTcpSocket.default_cert_store, + verify_mode: OpenSSL::SSL::VERIFY_PEER + ) + @socket = socket + + @hostname = hostname + @headers = headers + @cert_store = cert_store + @verify_mode = verify_mode + + super(secure_socket) + end + + protected + + def secure_socket + # Wrap the provided TCP socket with an SSLSocket + OpenSSL::SSL::SSLSocket.new(@socket, openssl_context).tap do |socket| + # support SNI, see https://www.cloudflare.com/en-gb/learning/ssl/what-is-sni/ + # don't set SNI hostname for IP address per RFC 6066, section 3. + socket.hostname = @hostname unless ip_address? + + # Establish secure connection + socket.connect + socket.post_connection_check(@hostname) + end + end + + def ip_address? + @hostname.match?(Resolv::IPv4::Regex) || + @hostname.match?(Resolv::IPv6::Regex) + end + + def openssl_context + OpenSSL::SSL::SSLContext.new.tap do |ctx| + # Set the certificate store + ctx.cert_store = @cert_store + + # Verify the TLS peer by default unless a verify mode is specified + ctx.verify_mode = @verify_mode + + # Avoid openssl warning on hostname verification for IP address + ctx.verify_hostname = false if ip_address? + end + end + end + end +end diff --git a/app/domain/authentication/authn_k8s/web_socket_client.rb b/app/domain/authentication/authn_k8s/web_socket_client.rb index 8ccd1e413b..078f4df877 100644 --- a/app/domain/authentication/authn_k8s/web_socket_client.rb +++ b/app/domain/authentication/authn_k8s/web_socket_client.rb @@ -1,115 +1,82 @@ +# frozen_string_literal: true + ## This code is based on github.com/shokai/websocket-client-simple (MIT License) require 'event_emitter' require 'websocket' require 'resolv' require 'openssl' +require 'uri' # Utility class for processing WebSocket messages. +# +# :reek:InstanceVariableAssumption for @frame and @handshake_finished. +# :reek:RepeatedConditional for secure? checks. module Authentication module AuthnK8s class WebSocketClient include EventEmitter - attr_reader :url, :handshake - def self.connect(url, options = {}) - client = WebSocketClient.new + def self.connect(url, **options) + client = WebSocketClient.new(url, **options) yield(client) if block_given? - client.connect(url, options) + client.connect client end - # connect provides options :hostname, :headers, :ssl_version, :cert_store, :verify_mode - def connect(url, options = {}) - return if @socket + # Used by WebSocketClientEventHandler + attr_reader :handshake - @url = url - uri = URI.parse(url) - is_secure_connection = %w[https wss].include?(uri.scheme) - @socket = TCPSocket.new(uri.host, - uri.port || (is_secure_connection ? 443 : 80)) - if is_secure_connection - ctx = OpenSSL::SSL::SSLContext.new - ssl_version = options[:ssl_version] - ctx.ssl_version = ssl_version if ssl_version - ctx.verify_mode = options[:verify_mode] || OpenSSL::SSL::VERIFY_PEER # use VERIFY_PEER for verification - cert_store = options[:cert_store] - - unless cert_store - cert_store = OpenSSL::X509::Store.new - cert_store.set_default_paths - end - ctx.cert_store = cert_store - - use_sni = false - ssl_host_address = options[:hostname] || uri.host # use the param :hostname or default to the host of the url argument - - case uri.host - when Resolv::IPv4::Regex, Resolv::IPv6::Regex - # don't set SNI, as IP addresses in SNI is not valid - # per RFC 6066, section 3. - - # Avoid openssl warning - ctx.verify_hostname = false - else - use_sni = true - end + def initialize( + url, - @socket = ::OpenSSL::SSL::SSLSocket.new(@socket, ctx) + # Optional keyword arguments to configure the secure socket behavior + hostname: nil, + headers: nil, + cert_store: SecureTcpSocket.default_cert_store, + verify_mode: OpenSSL::SSL::VERIFY_PEER + ) + # Parse the given url to ensure it's valid + @uri = URI.parse(url) - # support SNI, see https://www.cloudflare.com/en-gb/learning/ssl/what-is-sni/ - @socket.hostname = ssl_host_address if use_sni + # Use the provided port or default to the standard ports + @port = @uri.port || (secure? ? 443 : 80) - @socket.connect + @hostname = hostname + @headers = headers + @cert_store = cert_store + @verify_mode = verify_mode + end - # mandatory hostname verification applicable to both hostnames and IP addresses - @socket.post_connection_check(ssl_host_address) - end - @handshake = ::WebSocket::Handshake::Client.new(url: url, headers: options[:headers]) - @handshaked = false - @pipe_broken = false - frame = ::WebSocket::Frame::Incoming::Client.new - @closed = false - once(:__close) do |err| - close - emit(:close, err) - end + def connect + # Do nothing if already connected + return if @socket - @thread = Thread.new do - until @closed - begin - unless recv_data = @socket.getc - sleep(1) - next - end - if @handshaked - frame << recv_data - while msg = frame.next - emit(:message, msg) - end - else - @handshake << recv_data + # Establish initial connection to server + open_socket - # completed handshake - if @handshake.finished? - @handshaked = true - emit(:open) - end - end - rescue => e - emit(:error, e) - end - end - end + # If the connection uses TLS, establish the secure context + secure_socket if secure? + # Begin websocket IO loop in a separate thread + begin_event_loop + + # Send initial websocket handshake + @handshake ||= WebSocket::Handshake::Client.new( + url: @uri.to_s, + headers: @headers + ) @socket.write(@handshake.to_s) end def send(data, opt = { type: :text }) - return if !@handshaked || @closed + return if !@handshake_finished || @closed type = opt[:type] - frame = ::WebSocket::Frame::Outgoing::Client.new(data: data, type: type, version: @handshake.version) + frame = ::WebSocket::Frame::Outgoing::Client.new( + data: data, + type: type, version: @handshake.version + ) begin @socket.write(frame.to_s) rescue Errno::EPIPE => e @@ -124,10 +91,13 @@ def close unless @pipe_broken send(nil, type: :close) end + @closed = true @socket&.close @socket = nil + emit(:__close) + Thread.kill(@thread) if @thread end @@ -135,6 +105,104 @@ def open? @handshake.finished? && !@closed end + protected + + # :reek:DuplicateMethodCall for @uri.host + def open_socket + @socket = if proxy_uri + ProxiedTcpSocket.new( + proxy_uri: proxy_uri, + destination_host: @uri.host, + destination_port: @port + ).tcp_socket + else + TCPSocket.new(@uri.host, @port) + end + end + + # Wrap the given tcp_socket in an SSL socket to secure the connection + def secure_socket + @socket = SecureTcpSocket.new( + socket: @socket, + hostname: @hostname || @uri.host, + cert_store: @cert_store, + verify_mode: @verify_mode + ) + end + + # This returns the proxy url relevant to the connection from the + # environment. If the server connection uses TLS, then use the + # https_proxy value, otherwise use the http_proxy value. + def proxy_uri + @proxy_uri ||= begin + proxy_url = if secure? + ENV['https_proxy'] || ENV['HTTPS_PROXY'] + else + ENV['http_proxy'] || ENV['HTTP_PROXY'] + end + + URI.parse(proxy_url) + rescue URI::InvalidURIError + nil + end + end + + def secure? + %w[https wss].include?(@uri.scheme) + end + + # :reek:TooManyStatements + def begin_event_loop + @handshake_finished = false + @pipe_broken = false + @closed = false + + # Set up event handler with the websocket is closed + once(:__close) do |err| + close + emit(:close, err) + end + + @thread = Thread.new do + until @closed + begin + unless recv_data = @socket.getc + sleep(1) + next + end + + if @handshake_finished + process_incoming_data(recv_data) + else + process_handshake_data(recv_data) + end + rescue => e + emit(:error, e) + end + end + end + end + + def process_incoming_data(recv_data) + # Initialize the frame if this is the first data received + @frame ||= WebSocket::Frame::Incoming::Client.new + + # Add data to the frame and handle websocket events + @frame << recv_data + while msg = @frame.next + emit(:message, msg) + end + end + + def process_handshake_data(recv_data) + @handshake << recv_data + + # Continue waiting if the websocket handshake isn't finished + return unless @handshake.finished? + + @handshake_finished = true + emit(:open) + end end end end diff --git a/spec/app/domain/authentication/authn_k8s/proxied_tcp_socket_spec.rb b/spec/app/domain/authentication/authn_k8s/proxied_tcp_socket_spec.rb new file mode 100644 index 0000000000..46781e712d --- /dev/null +++ b/spec/app/domain/authentication/authn_k8s/proxied_tcp_socket_spec.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'openssl' +require 'stringio' + +require 'domain/authentication/authn_k8s/proxied_tcp_socket' + +describe Authentication::AuthnK8s::ProxiedTcpSocket do + describe '#new' do + let(:proxy_uri) { URI.parse("http://proxy.local:8080") } + let(:destination_host) { 'destination.example.com' } + let(:destination_port) { 443 } + let(:timeout) { 0.1 } + + let(:proxy_response) do + "200 connection established\r\n\r\n" + end + + let(:proxy_data) { StringIO.new } + + let(:tcp_socket_double) do + instance_double(TCPSocket).tap do |tcp_socket_double| + allow(tcp_socket_double).to receive(:write) do |value| + proxy_data << value + end + + allow(tcp_socket_double).to receive(:read).and_return(proxy_response) + end + end + + subject do + described_class.new( + proxy_uri: proxy_uri, + destination_host: destination_host, + destination_port: destination_port, + timeout: timeout + ) + end + + before do + allow(TCPSocket).to receive(:new).and_return(tcp_socket_double) + + # IO#select requires an actual IO device, so we must mock the call and return + # whether it is ready or not + allow(IO).to receive(:select).and_return([[tcp_socket_double], nil, nil]) + end + + it "establishes a TCP connection through the configured proxy" do + expect(TCPSocket).to receive(:new).with( + proxy_uri.host, + proxy_uri.port, + connect_timeout: timeout + ) + subject + end + + it "sends the connect messages" do + subject + expect(proxy_data.string).to include( + "CONNECT destination.example.com:443 HTTP/1.1\r\n" \ + "Host: destination.example.com\r\n\r\n" + ) + end + + context "when the proxy connection fails" do + let(:proxy_response) do + "500 internal server error\r\n\r\n" + end + + it "raises an exception" do + expect { subject }.to raise_error( + RuntimeError, + "Proxy ('proxy.local:8080') returned an invalid response: " \ + "'500 internal server error'" + ) + end + end + + context "when proxy authorization is set" do + let(:proxy_uri) { URI.parse("http://user:pass@proxy.local:8080") } + + it "include the proxy authorization header" do + subject + + auth_value = Base64.strict_encode64( + "#{proxy_uri.user}:#{proxy_uri.password}" + ) + expect(proxy_data.string).to include( + "Proxy-Authorization: Basic #{auth_value}" + ) + end + end + + context "when only proxy username is set" do + let(:proxy_uri) { URI.parse("http://user@proxy.local:8080") } + + it "doesn't include the proxy authorization header" do + subject + + expect(proxy_data.string).not_to include("Proxy-Authorization:") + end + end + end +end \ No newline at end of file diff --git a/spec/app/domain/authentication/authn_k8s/web_socket_client_spec_spec.rb b/spec/app/domain/authentication/authn_k8s/web_socket_client_spec.rb similarity index 98% rename from spec/app/domain/authentication/authn_k8s/web_socket_client_spec_spec.rb rename to spec/app/domain/authentication/authn_k8s/web_socket_client_spec.rb index 39e28fd9a1..0dc1700d7f 100644 --- a/spec/app/domain/authentication/authn_k8s/web_socket_client_spec_spec.rb +++ b/spec/app/domain/authentication/authn_k8s/web_socket_client_spec.rb @@ -3,6 +3,7 @@ # Run this file by calling: # bundle exec rspec spec/app/domain/authentication/authn_k8s/web_socket_client_spec_spec.rb --format documentation +require 'spec_helper' require 'openssl' require 'domain/authentication/authn_k8s/web_socket_client' @@ -21,20 +22,20 @@ end describe 'Authentication::AuthnK8s::WebSocketClient' do - context 'server running' do + context 'server running' do context 'without TLS' do before(:example) do @test_server = WebSocketTestServer.new @client = nil end - + after(:example) do @test_server.close @client && @client.close @test_server = nil @client = nil end - + it 'has good handshake with no options' do @test_server.add_websocket @test_server.run @@ -43,7 +44,7 @@ expect(@test_server.good_handshake?).to be_truthy expect(@client.open?).to be_truthy end - + it 'has good handshake with options' do @test_server.add_websocket @test_server.run @@ -53,7 +54,7 @@ expect(@test_server.good_handshake?).to be_truthy expect(@client.open?).to be_truthy end - + it 'is not open for communication without a good handshake' do @test_server.add_bad_websocket @test_server.run @@ -80,13 +81,13 @@ it 'fails cert verification without options' do @test_server.add_websocket @test_server.run - expect { + expect { @client = Authentication::AuthnK8s::WebSocketClient.connect("wss://localhost:#{@test_server.port}") }.to raise_error(OpenSSL::SSL::SSLError, nil) { |error| - expect(error.message).to eq("SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)") + expect(error.message).to eq("SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)") } end - + it 'passes all TLS verifications with good options' do @test_server.add_websocket @test_server.run @@ -152,10 +153,10 @@ it 'fails cert verification without options' do @test_server.add_websocket @test_server.run - expect { + expect { @client = Authentication::AuthnK8s::WebSocketClient.connect("wss://localhost:#{@test_server.port}") }.to raise_error(OpenSSL::SSL::SSLError, nil) { |error| - expect(error.message).to eq("SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)") + expect(error.message).to eq("SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)") } end From cacbcead2999dc4aaee97b8161d57a59ab605960 Mon Sep 17 00:00:00 2001 From: Andy Tinkham Date: Thu, 13 Apr 2023 13:30:19 -0500 Subject: [PATCH 12/42] Update nokogiri & rails in Gemfile.lock, and nokogiri & commonmarker in docs/Gemfile.lock Signed-off-by: Andy Tinkham --- CHANGELOG.md | 7 +++ Gemfile.lock | 130 ++++++++++++++++++++++++---------------------- NOTICES.txt | 96 ++++++++++------------------------ docs/Gemfile.lock | 4 +- 4 files changed, 102 insertions(+), 135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c7c74395..4051f1413f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. allows for an HTTP proxy between Conjur and the Kubernetes API. [cyberark/conjur#2766](https://github.com/cyberark/conjur/pull/2766) +### Security +- Updated nokogiri to 1.14.3 for CVE-2023-29469 and CVE-2023-28484 and rails to + 6.1.7.3 for CVE-2023-28120 in Gemfile.lock, nokogiri to 1.1.4.3 for CVE-2023-29469 + and commonmarker to 0.23.9 for CVE-2023-24824 and CVE-2023-26485 in docs/Gemfile.lock + (all Medium severity issues flagged by Dependabot) + [cyberark/conjur#2776](https://github.com/cyberark/conjur/pull/2776) + ## [1.19.2] - 2023-02-01 ### Added diff --git a/Gemfile.lock b/Gemfile.lock index 4bd9cbab8a..7082556903 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,60 +8,60 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (6.1.7.1) - actionpack (= 6.1.7.1) - activesupport (= 6.1.7.1) + actioncable (6.1.7.3) + actionpack (= 6.1.7.3) + activesupport (= 6.1.7.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.7.1) - actionpack (= 6.1.7.1) - activejob (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + actionmailbox (6.1.7.3) + actionpack (= 6.1.7.3) + activejob (= 6.1.7.3) + activerecord (= 6.1.7.3) + activestorage (= 6.1.7.3) + activesupport (= 6.1.7.3) mail (>= 2.7.1) - actionmailer (6.1.7.1) - actionpack (= 6.1.7.1) - actionview (= 6.1.7.1) - activejob (= 6.1.7.1) - activesupport (= 6.1.7.1) + actionmailer (6.1.7.3) + actionpack (= 6.1.7.3) + actionview (= 6.1.7.3) + activejob (= 6.1.7.3) + activesupport (= 6.1.7.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.7.1) - actionview (= 6.1.7.1) - activesupport (= 6.1.7.1) + actionpack (6.1.7.3) + actionview (= 6.1.7.3) + activesupport (= 6.1.7.3) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.7.1) - actionpack (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + actiontext (6.1.7.3) + actionpack (= 6.1.7.3) + activerecord (= 6.1.7.3) + activestorage (= 6.1.7.3) + activesupport (= 6.1.7.3) nokogiri (>= 1.8.5) - actionview (6.1.7.1) - activesupport (= 6.1.7.1) + actionview (6.1.7.3) + activesupport (= 6.1.7.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.7.1) - activesupport (= 6.1.7.1) + activejob (6.1.7.3) + activesupport (= 6.1.7.3) globalid (>= 0.3.6) - activemodel (6.1.7.1) - activesupport (= 6.1.7.1) - activerecord (6.1.7.1) - activemodel (= 6.1.7.1) - activesupport (= 6.1.7.1) - activestorage (6.1.7.1) - actionpack (= 6.1.7.1) - activejob (= 6.1.7.1) - activerecord (= 6.1.7.1) - activesupport (= 6.1.7.1) + activemodel (6.1.7.3) + activesupport (= 6.1.7.3) + activerecord (6.1.7.3) + activemodel (= 6.1.7.3) + activesupport (= 6.1.7.3) + activestorage (6.1.7.3) + actionpack (= 6.1.7.3) + activejob (= 6.1.7.3) + activerecord (= 6.1.7.3) + activesupport (= 6.1.7.3) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (6.1.7.1) + activesupport (6.1.7.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -107,7 +107,7 @@ GEM rspec (>= 2.14, < 4) coderay (1.1.3) command_class (0.0.2) - concurrent-ruby (1.2.0) + concurrent-ruby (1.2.2) conjur-api (5.4.0) activesupport (>= 4.2) addressable (~> 2.0) @@ -217,7 +217,7 @@ GEM ffi (>= 1.0.0) rake gli (2.21.0) - globalid (1.0.1) + globalid (1.1.0) activesupport (>= 5.0) haikunator (1.1.1) hana (1.3.7) @@ -268,10 +268,10 @@ GEM listen (3.7.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.19.1) + loofah (2.20.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.8.0.1) + mail (2.8.1) mini_mime (>= 0.1.1) net-imap net-pop @@ -282,7 +282,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) mini_mime (1.1.2) - minitest (5.17.0) + minitest (5.18.0) multi_json (1.15.0) multi_test (0.1.2) net-imap (0.3.4) @@ -297,10 +297,10 @@ GEM net-protocol net-ssh (6.1.0) netrc (0.11.0) - nio4r (2.5.8) - nokogiri (1.14.0-x86_64-darwin) + nio4r (2.5.9) + nokogiri (1.14.3-x86_64-darwin) racc (~> 1.4) - nokogiri (1.14.0-x86_64-linux) + nokogiri (1.14.3-x86_64-linux) racc (~> 1.4) openid_connect (1.3.0) activemodel @@ -337,22 +337,22 @@ GEM json-jwt (>= 1.11.0) rack (>= 2.1.0) rack-rewrite (1.5.1) - rack-test (2.0.2) + rack-test (2.1.0) rack (>= 1.3) - rails (6.1.7.1) - actioncable (= 6.1.7.1) - actionmailbox (= 6.1.7.1) - actionmailer (= 6.1.7.1) - actionpack (= 6.1.7.1) - actiontext (= 6.1.7.1) - actionview (= 6.1.7.1) - activejob (= 6.1.7.1) - activemodel (= 6.1.7.1) - activerecord (= 6.1.7.1) - activestorage (= 6.1.7.1) - activesupport (= 6.1.7.1) + rails (6.1.7.3) + actioncable (= 6.1.7.3) + actionmailbox (= 6.1.7.3) + actionmailer (= 6.1.7.3) + actionpack (= 6.1.7.3) + actiontext (= 6.1.7.3) + actionview (= 6.1.7.3) + activejob (= 6.1.7.3) + activemodel (= 6.1.7.3) + activerecord (= 6.1.7.3) + activestorage (= 6.1.7.3) + activesupport (= 6.1.7.3) bundler (>= 1.15.0) - railties (= 6.1.7.1) + railties (= 6.1.7.3) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -361,7 +361,7 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.4.4) + rails-html-sanitizer (1.5.0) loofah (~> 2.19, >= 2.19.1) rails_12factor (0.0.3) rails_serve_static_assets @@ -369,9 +369,9 @@ GEM rails_layout (1.0.42) rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (6.1.7.1) - actionpack (= 6.1.7.1) - activesupport (= 6.1.7.1) + railties (6.1.7.3) + actionpack (= 6.1.7.3) + activesupport (= 6.1.7.3) method_source rake (>= 12.2) thor (~> 1.0) @@ -466,7 +466,11 @@ GEM ffi (~> 1.1) table_print (1.5.7) thor (1.2.1) +<<<<<<< HEAD timeout (0.3.1) +======= + timeout (0.3.2) +>>>>>>> 70809583 (Update nokogiri & rails in Gemfile.lock, and nokogiri & commonmarker in docs/Gemfile.lock) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unf (0.1.4) diff --git a/NOTICES.txt b/NOTICES.txt index f4e9647e67..9f776f0a92 100644 --- a/NOTICES.txt +++ b/NOTICES.txt @@ -13,18 +13,18 @@ Section 1: Apache-2.0 Section 2: BSD-2-Clause ->>> https://rubygems.org/gems/base32-crockford/versions/0.1.0 >>> https://rubygems.org/gems/pg/versions/1.2.3 >>> https://rubygems.org/gems/websocket/versions/1.2.9 Section 3: BSD-3-Clause +>>> https://rubygems.org/gems/base32-crockford/versions/0.1.0 >>> https://rubygems.org/gems/ffi/versions/1.15.4 >>> https://rubygems.org/gems/puma/versions/5.6.4 Section 4: MIT ->>> https://rubygems.org/gems/activesupport/versions/6.1.7.1 +>>> https://rubygems.org/gems/activesupport/versions/6.1.7.3 >>> https://rubygems.org/gems/anyway_config/versions/2.2.3 >>> https://rubygems.org/gems/base58/versions/0.2.3 >>> https://rubygems.org/gems/bcrypt/versions/3.1.16 @@ -40,19 +40,19 @@ Section 4: MIT >>> https://rubygems.org/gems/jwt/versions/2.2.2 >>> https://rubygems.org/gems/kubeclient/versions/4.9.3 >>> https://rubygems.org/gems/listen/versions/3.7.0 ->>> https://rubygems.org/gems/loofah/versions/2.19.1 +>>> https://rubygems.org/gems/loofah/versions/2.20.0 >>> https://rubygems.org/gems/net-ldap/versions/0.17.0 ->>> https://rubygems.org/gems/nokogiri/versions/1.13.10 +>>> https://rubygems.org/gems/nokogiri/versions/1.14.3 >>> https://rubygems.org/gems/openid_connect/versions/1.3.0 >>> https://rubygems.org/gems/rack-rewrite/versions/1.5.1 ->>> https://rubygems.org/gems/rails/versions/6.1.7.1 +>>> https://rubygems.org/gems/rails/versions/6.1.7.3 >>> https://rubygems.org/gems/rake/versions/13.0.6 >>> https://rubygems.org/gems/sequel/versions/5.51.0 >>> https://rubygems.org/gems/sequel-pg_advisory_locking/versions/1.0.1 >>> https://rubygems.org/gems/sequel-postgres-schemata/versions/0.1.3 >>> https://rubygems.org/gems/sequel-rails/versions/1.1.1 >>> https://rubygems.org/gems/simplecov/versions/0.21.2 ->>> https://rubygems.org/gems/slosilo/versions/3.0.0 +>>> https://rubygems.org/gems/slosilo/versions/3.0.1 >>> https://rubygems.org/gems/event_emitter/versions/0.2.6 APPENDIX: Standard License Files and Templates @@ -247,7 +247,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MIT License is applicable to the following component(s). ->>> https://rubygems.org/gems/activesupport/versions/6.1.7.1 +>>> https://rubygems.org/gems/activesupport/versions/6.1.7.3 Copyright (c) 2005-2018 David Heinemeier Hansson @@ -614,7 +614,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/loofah/versions/2.19.1 +>>> https://rubygems.org/gems/loofah/versions/2.20.0 Copyright (c) 2009 -- 2018 by Mike Dalessio, Bryan Helmkamp @@ -636,28 +636,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/mini_racer/versions/0.2.9 - -Copyright (c) 2016-2019, the mini_racer project authors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - >>> https://rubygems.org/gems/net-ldap/versions/0.17.0 Copyright 2006–2011 by Francis Cianfrocca and other contributors. @@ -680,7 +658,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/nokogiri/versions/1.13.10 +>>> https://rubygems.org/gems/nokogiri/versions/1.14.3 Copyright 2008 -- 2018 by Aaron Patterson, Mike Dalessio, Charles Nutter, Sergio Arbeo, Patrick Mahoney, Yoko Harada, Akinori MUSHA, John Shahid, Lars Kanis @@ -748,7 +726,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/rails/versions/6.1.7.1 +>>> https://rubygems.org/gems/rails/versions/6.1.7.3 Copyright (c) 2005-2018 David Heinemeier Hansson @@ -792,27 +770,27 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/ruby_dep/versions/1.3.1 +>>> >>> https://rubygems.org/gems/sequel/versions/5.51.0 -Copyright (c) 2016 Cezary Baginski +Copyright (c) 2007-2008 Sharon Rosner +Copyright (c) 2008-2023 Jeremy Evans Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. >>> https://rubygems.org/gems/sequel-pg_advisory_locking/versions/1.0.1 @@ -880,28 +858,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/sequel/versions/5.50.0 - -Copyright (c) 2007-2008 Sharon Rosner -Copyright (c) 2008-2021 Jeremy Evans - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - >>> https://rubygems.org/gems/simplecov/versions/0.21.2 Copyright (c) 2010-2015 Christoph Olszowka @@ -924,7 +880,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ->>> https://rubygems.org/gems/slosilo/versions/3.0.0 +>>> https://rubygems.org/gems/slosilo/versions/3.0.1 Copyright (c) 2020 CyberArk Software Ltd. All rights reserved. diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 45958c5a5e..93168789b8 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -14,7 +14,7 @@ GEM execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.23.8) + commonmarker (0.23.9) concurrent-ruby (1.2.2) dnsruby (1.61.9) simpleidn (~> 0.1) @@ -213,7 +213,7 @@ GEM jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.18.0) - nokogiri (1.14.2) + nokogiri (1.14.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (4.25.1) From 57487858ab67e05143548f691a72c16d3d996a2d Mon Sep 17 00:00:00 2001 From: Glen Johnson Date: Wed, 12 Apr 2023 11:24:28 -0400 Subject: [PATCH 13/42] Remove duplicate changelog version and fix unreleased changes --- CHANGELOG.md | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4051f1413f..2e7fe7c5e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,29 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Nothing should go in this section, please add to the latest unreleased version (and update the corresponding date), or add a new version. -## [1.19.3] - 2023-03-21 - -### Changed -- Removes support for disabling the `CONJUR_FEATURE_PKCE_SUPPORT_ENABLED` flag. - [cyberark/conjur#2713](https://github.com/cyberark/conjur/pull/2713) -- Routes on the `/roles/` API endpoints now correctly verify the existing of - a Role and return `404` when it doesn't exist or the caller has insufficient - privilege. - [cyberark/conjur#2755](https://github.com/cyberark/conjur/pull/2755) - -### Fixed -- Incomplete HTTP proxy support in the Kubernetes Authenticator is fixed. This - allows for an HTTP proxy between Conjur and the Kubernetes API. - [cyberark/conjur#2766](https://github.com/cyberark/conjur/pull/2766) - -### Security -- Updated nokogiri to 1.14.3 for CVE-2023-29469 and CVE-2023-28484 and rails to - 6.1.7.3 for CVE-2023-28120 in Gemfile.lock, nokogiri to 1.1.4.3 for CVE-2023-29469 - and commonmarker to 0.23.9 for CVE-2023-24824 and CVE-2023-26485 in docs/Gemfile.lock - (all Medium severity issues flagged by Dependabot) - [cyberark/conjur#2776](https://github.com/cyberark/conjur/pull/2776) - -## [1.19.2] - 2023-02-01 +## [1.19.3] - 2023-04-17 ### Added - Conjur now logs when it detects that the Conjur configuration file @@ -43,11 +21,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. access controls work as expected for this role to access itself. [cyberark/conjur#2757](https://github.com/cyberark/conjur/pull/2757) +### Changed +- Removes support for disabling the `CONJUR_FEATURE_PKCE_SUPPORT_ENABLED` flag. + [cyberark/conjur#2713](https://github.com/cyberark/conjur/pull/2713) +- Routes on the `/roles/` API endpoints now correctly verify the existing of + a Role and return `404` when it doesn't exist or the caller has insufficient + privilege. + [cyberark/conjur#2755](https://github.com/cyberark/conjur/pull/2755) + ### Fixed - Fixed a thread-safety bug in secret retrieval when multiple threads attempt to decrypt a secret value with Slosilo/OpenSSL. [cyberark/slosilo#31](https://github.com/cyberark/slosilo/pull/31) [cyberark/conjur#2718](https://github.com/cyberark/conjur/pull/2718) +- Incomplete HTTP proxy support in the Kubernetes Authenticator is fixed. This + allows for an HTTP proxy between Conjur and the Kubernetes API. + [cyberark/conjur#2766](https://github.com/cyberark/conjur/pull/2766) ### Security - Updated github-pages version in docs/Gemfile to allow upgrading activesupport @@ -57,6 +46,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [cyberark/conjur#2739](https://github.com/cyberark/conjur/pull/2739) - Upgraded rack to v2.2.6.4 to resolve CVE-2023-27539 [cyberark/conjur#2750](https://github.com/cyberark/conjur/pull/2750) +- Updated nokogiri to 1.14.3 for CVE-2023-29469 and CVE-2023-28484 and rails to + 6.1.7.3 for CVE-2023-28120 in Gemfile.lock, nokogiri to 1.1.4.3 for CVE-2023-29469 + and commonmarker to 0.23.9 for CVE-2023-24824 and CVE-2023-26485 in docs/Gemfile.lock + (all Medium severity issues flagged by Dependabot) + [cyberark/conjur#2776](https://github.com/cyberark/conjur/pull/2776) ## [1.19.2] - 2022-01-13 @@ -126,7 +120,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - List resources request (`GET /resources`) now produce audit events. - ([cyberark/conjur#2652](https://github.com/cyberark/conjur/pull/2652) + [cyberark/conjur#2652](https://github.com/cyberark/conjur/pull/2652) ### Changed - AWS Access Key Rotation now preserves only one key @@ -1033,7 +1027,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - The first tagged version. -[Unreleased]: https://github.com/cyberark/conjur/compare/v1.19.0...HEAD +[Unreleased]: https://github.com/cyberark/conjur/compare/v1.19.3...HEAD +[1.19.3]: https://github.com/cyberark/conjur/compare/v1.19.2...v1.19.3 +[1.19.2]: https://github.com/cyberark/conjur/compare/v1.19.1...v1.19.2 +[1.19.1]: https://github.com/cyberark/conjur/compare/v1.19.0...v1.19.1 [1.19.0]: https://github.com/cyberark/conjur/compare/v1.18.5...v1.19.0 [1.18.5]: https://github.com/cyberark/conjur/compare/v1.18.4...v1.18.5 [1.18.4]: https://github.com/cyberark/conjur/compare/v1.18.3...v1.18.4 From e9e9dcb6fe423af244c89309c08766774844e7f1 Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Wed, 5 Apr 2023 09:28:20 -0400 Subject: [PATCH 14/42] Dev/start: order --help flag list alphabetically --- dev/start | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/dev/start b/dev/start index e06baedb56..2b8f3814c7 100755 --- a/dev/start +++ b/dev/start @@ -26,16 +26,16 @@ enabled_authenticators="$default_authenticators" env_args=() # Services and authenticators to start, enabled by cmd line flags. -ENABLE_AUTHN_LDAP=false -ENABLE_AUTHN_IAM=false +ENABLE_AUDIT=false ENABLE_AUTHN_AZURE=false -ENABLE_AUTHN_OIDC=false ENABLE_AUTHN_GCP=false +ENABLE_AUTHN_IAM=false ENABLE_AUTHN_JWT=false +ENABLE_AUTHN_LDAP=false +ENABLE_AUTHN_OIDC=false ENABLE_OIDC_ADFS=false ENABLE_OIDC_OKTA=false ENABLE_ROTATORS=false -ENABLE_AUDIT=false main() { unset COMPOSE_PROJECT_NAME @@ -83,30 +83,21 @@ the Conjur container. To start the application server, run: # conjurctl server Usage: start [options] + --audit Starts with the audit engine and database enabled + --authn-azure Starts with authn-azure/prod as authenticator + --authn-gcp Starts with authn-gcp as authenticator + --authn-iam Starts with authn-iam/prod as authenticator + --authn-jwt Starts with authn-jwt as authenticator --authn-ldap Starts OpenLDAP server and loads a demo policy to enable authentication via: 'curl -X POST -d "alice" http://localhost:3000/authn-ldap/test/cucumber/alice/authenticate' - --rotators Starts a cucumber and test postgres container. - Drops you into the cucumber container. - You then manually start 'conjurctl server' in another tab. - - --authn-iam Starts with authn-iam/prod as authenticator - - --authn-azure Starts with authn-azure/prod as authenticator - --authn-oidc Starts with authn-oidc/keycloak as authenticator - - --authn-gcp Starts with authn-gcp as authenticator - - --authn-jwt Starts with authn-jwt as authenticator - + -h, --help Shows this help message. --oidc-adfs Adds to authn-oidc adfs static env configuration - --oidc-okta Adds to authn-oidc okta static env configuration - - --audit Starts with the audit engine and database enabled - - -h, --help Shows this help message. + --rotators Starts a cucumber and test postgres container. + Drops you into the cucumber container. + You then manually start 'conjurctl server' in another tab. EOF exit } @@ -114,17 +105,17 @@ EOF parse_options() { while true ; do case "$1" in - --authn-iam ) ENABLE_AUTHN_IAM=true ; shift ;; + --audit ) ENABLE_AUDIT=true ; shift ;; --authn-azure ) ENABLE_AUTHN_AZURE=true ; shift ;; - --authn-ldap ) ENABLE_AUTHN_LDAP=true ; shift ;; --authn-gcp ) ENABLE_AUTHN_GCP=true ; shift ;; + --authn-iam ) ENABLE_AUTHN_IAM=true ; shift ;; --authn-jwt ) ENABLE_AUTHN_JWT=true ; shift ;; + --authn-ldap ) ENABLE_AUTHN_LDAP=true ; shift ;; --authn-oidc ) ENABLE_AUTHN_OIDC=true ; shift ;; + -h | --help ) print_help ; shift ;; --oidc-adfs ) ENABLE_OIDC_ADFS=true ; shift ;; --oidc-okta ) ENABLE_OIDC_OKTA=true ; shift ;; --rotators ) ENABLE_ROTATORS=true ; shift ;; - --audit ) ENABLE_AUDIT=true ; shift ;; - -h | --help ) print_help ; shift ;; * ) if [ -z "$1" ]; then break From 68e4934f540a0b3d97d7f74e68f944887a323977 Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Wed, 5 Apr 2023 10:52:15 -0400 Subject: [PATCH 15/42] Dev/start: isolate Keycloak setup, generalize AuthnOIDC configuration --- .../{okta-users.yml => okta-2-users.yml} | 0 dev/start | 166 +++++++++--------- 2 files changed, 86 insertions(+), 80 deletions(-) rename dev/policies/authenticators/authn-oidc/{okta-users.yml => okta-2-users.yml} (100%) diff --git a/dev/policies/authenticators/authn-oidc/okta-users.yml b/dev/policies/authenticators/authn-oidc/okta-2-users.yml similarity index 100% rename from dev/policies/authenticators/authn-oidc/okta-users.yml rename to dev/policies/authenticators/authn-oidc/okta-2-users.yml diff --git a/dev/start b/dev/start index 2b8f3814c7..5a9461ace2 100755 --- a/dev/start +++ b/dev/start @@ -34,6 +34,7 @@ ENABLE_AUTHN_JWT=false ENABLE_AUTHN_LDAP=false ENABLE_AUTHN_OIDC=false ENABLE_OIDC_ADFS=false +ENABLE_OIDC_KEYCLOAK=false ENABLE_OIDC_OKTA=false ENABLE_ROTATORS=false @@ -91,9 +92,13 @@ Usage: start [options] --authn-ldap Starts OpenLDAP server and loads a demo policy to enable authentication via: 'curl -X POST -d "alice" http://localhost:3000/authn-ldap/test/cucumber/alice/authenticate' - --authn-oidc Starts with authn-oidc/keycloak as authenticator -h, --help Shows this help message. --oidc-adfs Adds to authn-oidc adfs static env configuration + --oidc-keycloak Starts with authn-oidc/keycloak and authn-oidc/keycloak2 as + available authenticators. Service authn-oidc/keycloak uses + AuthnOIDC V1 (based on ID token property validation), and + authn-oidc/keycloak2 uses AuthnOIDC V2 (based on the Authz + Code with PKCE flow). --oidc-okta Adds to authn-oidc okta static env configuration --rotators Starts a cucumber and test postgres container. Drops you into the cucumber container. @@ -111,10 +116,10 @@ parse_options() { --authn-iam ) ENABLE_AUTHN_IAM=true ; shift ;; --authn-jwt ) ENABLE_AUTHN_JWT=true ; shift ;; --authn-ldap ) ENABLE_AUTHN_LDAP=true ; shift ;; - --authn-oidc ) ENABLE_AUTHN_OIDC=true ; shift ;; -h | --help ) print_help ; shift ;; - --oidc-adfs ) ENABLE_OIDC_ADFS=true ; shift ;; - --oidc-okta ) ENABLE_OIDC_OKTA=true ; shift ;; + --oidc-adfs ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_ADFS=true ; shift ;; + --oidc-keycloak ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_KEYCLOAK=true ; shift ;; + --oidc-okta ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_OKTA=true ; shift ;; --rotators ) ENABLE_ROTATORS=true ; shift ;; * ) if [ -z "$1" ]; then @@ -142,18 +147,6 @@ client_add_secret() { conjur variable values add "$variable" "$value" } -configure_oidc_providers() { - # Start conjur again, since it is recreating by docker-compose because of - # dependency with keycloak - start_conjur_server - wait_for_keycloak_server - fetch_oidc_certificates - configure_oidc_authenticators - enable_oidc_authenticators - create_keycloak_users - echo "keycloak admin console url: http://0.0.0.0:7777/auth/admin" -} - start_conjur_server() { echo "Starting Conjur server" docker-compose exec -d conjur conjurctl server @@ -174,74 +167,97 @@ wait_for_conjur() { } configure_oidc_authenticators() { - # add variables' values for keycloak - echo "Setting keycloak variables values in conjur" - client_load_policy \ - "/src/conjur-server/ci/test_suites/authenticators_oidc/policy.yml" + if [[ $ENABLE_OIDC_KEYCLOAK = true ]]; then + setup_keycloak + fi - client_add_secret \ - "conjur/authn-oidc/keycloak/provider-uri" \ - "https://keycloak:8443/auth/realms/master" + if [[ $ENABLE_OIDC_OKTA = true ]]; then + setup_okta + fi - client_add_secret \ - "conjur/authn-oidc/keycloak/id-token-user-property" "preferred_username" + if [[ $ENABLE_OIDC_ADFS = true ]]; then + setup_adfs + fi +} - # Specific for Keycloak Authenticator (for full flow) - client_load_policy '/src/conjur-server/dev/policies/authenticators/authn-oidc/keycloak2.yml' - client_add_secret 'conjur/authn-oidc/keycloak2/provider-uri' 'https://keycloak:8443/auth/realms/master' - client_add_secret 'conjur/authn-oidc/keycloak2/client-id' 'conjurClient' - client_add_secret 'conjur/authn-oidc/keycloak2/client-secret' '1234' - client_add_secret 'conjur/authn-oidc/keycloak2/claim-mapping' 'email' - client_add_secret 'conjur/authn-oidc/keycloak2/nonce' 'af88d8f8ff6631fb4cf0' - client_add_secret 'conjur/authn-oidc/keycloak2/state' 'd38e57e0fd47ccffa9c2' - client_add_secret 'conjur/authn-oidc/keycloak2/redirect_uri' 'http://localhost:3000/authn-oidc/keycloak2/cucumber/authenticate' +setup_keycloak() { + # Start keycloak docker-compose service + services+=(keycloak) + docker-compose up -d --no-deps "${services[@]}" - client_load_policy '/src/conjur-server/dev/policies/authenticators/authn-oidc/keycloak2-users.yml' + # Start conjur again, since it is recreating by docker-compose because of + # dependency with keycloak + start_conjur_server + wait_for_keycloak_server + fetch_keycloak_certificate + # Create Conjur AuthnOIDC services and users + configure_oidc_v1 \ + 'keycloak' 'https://keycloak:8443/auth/realms/master' \ + 'preferred_username' 'ci/test_suites/authenticators_oidc/policy.yml' + configure_oidc_v2 \ + 'keycloak2' 'https://keycloak:8443/auth/realms/master' \ + 'conjurClient' '1234' 'email' - if [[ $ENABLE_OIDC_OKTA = true ]]; then - # Specific for new OIDC Authenticator - client_load_policy '/src/conjur-server/dev/policies/authenticators/authn-oidc/okta-2.yml' - client_add_secret 'conjur/authn-oidc/okta-2/provider-uri' 'https://dev-92899796.okta.com/oauth2/default' - client_add_secret 'conjur/authn-oidc/okta-2/client-id' '0oa3w3xig6rHiu9yT5d7' - client_add_secret 'conjur/authn-oidc/okta-2/client-secret' 'e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj' - client_add_secret 'conjur/authn-oidc/okta-2/claim-mapping' 'preferred_username' - client_add_secret 'conjur/authn-oidc/okta-2/nonce' '1656b4264b60af659fce' - client_add_secret 'conjur/authn-oidc/okta-2/state' '4f413476ef7e2395f0af' - client_add_secret 'conjur/authn-oidc/okta-2/redirect_uri' 'http://localhost:3000/authn-oidc/okta-2/cucumber/authenticate' - - client_load_policy '/src/conjur-server/dev/policies/authenticators/authn-oidc/okta-users.yml' - fi + # Create users in Keycloak + create_keycloak_users - if [[ $ENABLE_OIDC_ADFS = true ]]; then - # add variables' values for ADFS - client_load_policy "/src/conjur-server/ci/authn-oidc/policy_adfs.yml" + echo "keycloak admin console url: http://0.0.0.0:7777/auth/admin" +} + +setup_okta() { + configure_oidc_v2 \ + 'okta-2' 'https://dev-92899796.okta.com/oauth2/default' \ + '0oa3w3xig6rHiu9yT5d7' 'e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj' \ + 'preferred_username' +} - client_add_secret \ - "conjur/authn-oidc/adfs/provider-uri" \ - "https://adfs4win2016.northeurope.cloudapp.azure.com" +setup_adfs() { + echo "Initialize ADFS certificate in conjur server" + docker-compose exec conjur \ + /src/conjur-server/dev/files/authn-oidc/adfs/fetchCertificate - client_add_secret \ - "conjur/authn-oidc/adfs/id-token-user-property" "unique_name" - fi + configure_oidc_v1 \ + 'adfs' 'https://adfs4win2016.northeurope.cloudapp.azure.com' \ + 'unique_name' 'ci/authn-oidc/policy_adfs.yml' } -fetch_oidc_certificates() { - fetch_keycloak_certificate +configure_oidc_v1() { + service_id="$1" + provider_uri="$2" + token_property="$3" + policy_path="$4" - if [[ $ENABLE_OIDC_ADFS = true ]]; then - echo "Initialize ADFS certificate in conjur server" - docker-compose exec conjur \ - /src/conjur-server/dev/files/authn-oidc/adfs/fetchCertificate - fi + client_load_policy "/src/conjur-server/$policy_path" + client_add_secret "conjur/authn-oidc/$service_id/provider-uri" "$provider_uri" + client_add_secret "conjur/authn-oidc/$service_id/id-token-user-property" "$token_property" +} + +configure_oidc_v2() { + service_id="$1" + provider_uri="$2" + client_id="$3" + client_secret="$4" + claim_mapping="$5" + + client_load_policy "/src/conjur-server/dev/policies/authenticators/authn-oidc/$service_id.yml" + client_add_secret "conjur/authn-oidc/$service_id/provider-uri" "$provider_uri" + client_add_secret "conjur/authn-oidc/$service_id/client-id" "$client_id" + client_add_secret "conjur/authn-oidc/$service_id/client-secret" "$client_secret" + client_add_secret "conjur/authn-oidc/$service_id/claim-mapping" "$claim_mapping" + client_add_secret "conjur/authn-oidc/$service_id/redirect_uri" "http://localhost:3000/authn-oidc/$service_id/cucumber/authenticate" + + client_load_policy "/src/conjur-server/dev/policies/authenticators/authn-oidc/$service_id-users.yml" } enable_oidc_authenticators() { - echo "Configuring Keycloak as OpenID provider for automatic testing" - # We enable an OIDC authenticator without a service-id to test that it's - # invalid. - enabled_authenticators="$enabled_authenticators,authn-oidc/keycloak,authn-oidc,authn-oidc/keycloak2" + if [[ $ENABLE_OIDC_KEYCLOAK = true ]]; then + echo "Configuring Keycloak as OpenID provider for manual testing" + # We enable an OIDC authenticator without a service-id to test that it's + # invalid. + enabled_authenticators="$enabled_authenticators,authn-oidc/keycloak,authn-oidc,authn-oidc/keycloak2" + fi if [[ $ENABLE_OIDC_OKTA = true ]]; then echo "Configuring OKTA as OpenID provider for manual testing" @@ -361,22 +377,12 @@ init_jwt() { } init_oidc() { - # ADFS and OKTA make no sense without OIDC. - if [[ $ENABLE_AUTHN_OIDC = false && - ($ENABLE_OIDC_ADFS = true || $ENABLE_OIDC_OKTA = true) ]] - then - echo "Error: --oidc-adfs and --oidc-okta both require --authn-oidc" - exit 1 - fi - if [[ $ENABLE_AUTHN_OIDC != true ]]; then return fi - services+=(keycloak) - docker-compose up -d --no-deps "${services[@]}" - - configure_oidc_providers + configure_oidc_authenticators + enable_oidc_authenticators if [[ $ENABLE_AUTHN_LDAP = true && $ENABLE_OIDC_OKTA = true ]]; then echo "Building & configuring Okta-LDAP agent" From 7f19283957c2a809c8b683fd6dd7ea7ae4621250 Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Mon, 10 Apr 2023 09:55:37 -0400 Subject: [PATCH 16/42] Add Identity-based AuthnOIDC to Conjur dev env --- .gitignore | 3 ++ .../authn-oidc/identity-users.template.yml | 6 +++ .../authenticators/authn-oidc/identity.yml | 38 +++++++++++++++++++ dev/secrets.yml | 3 ++ dev/start | 32 ++++++++++++++++ 5 files changed, 82 insertions(+) create mode 100644 dev/policies/authenticators/authn-oidc/identity-users.template.yml create mode 100644 dev/policies/authenticators/authn-oidc/identity.yml create mode 100644 dev/secrets.yml diff --git a/.gitignore b/.gitignore index d8d3be6c60..ede6e0d417 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,7 @@ gems/*/Gemfile.lock # Container commit marker conjur_git_commit +# AuthnOIDC V2 w/ Identity setup +dev/policies/authenticators/authn-oidc/identity-users.yml + VERSION diff --git a/dev/policies/authenticators/authn-oidc/identity-users.template.yml b/dev/policies/authenticators/authn-oidc/identity-users.template.yml new file mode 100644 index 0000000000..587af45811 --- /dev/null +++ b/dev/policies/authenticators/authn-oidc/identity-users.template.yml @@ -0,0 +1,6 @@ +- !user {{ IDENTITY_USER }} + +- !grant + members: + - !user {{ IDENTITY_USER }} + role: !group conjur/authn-oidc/identity/authenticatable diff --git a/dev/policies/authenticators/authn-oidc/identity.yml b/dev/policies/authenticators/authn-oidc/identity.yml new file mode 100644 index 0000000000..75f229bdbd --- /dev/null +++ b/dev/policies/authenticators/authn-oidc/identity.yml @@ -0,0 +1,38 @@ +- !policy + id: conjur/authn-oidc/identity + body: + - !webservice + + # Identity connection details + - !variable provider-uri + - !variable client-id + - !variable client-secret + + # URI of Conjur instance + - !variable redirect_uri + + # Defines the JWT claim to use as the Conjur identifier + - !variable claim-mapping + + # Group with permission to authenticate + - !group + id: authenticatable + annotations: + description: Users who can authenticate using this authenticator + + - !permit + role: !group authenticatable + privilege: [ read, authenticate ] + resource: !webservice + + # Create a web service for checking status + - !webservice status + + # Group of users who can check the status + - !group operators + + # Permit group to check the status + - !permit + role: !group operators + privilege: read + resource: !webservice status diff --git a/dev/secrets.yml b/dev/secrets.yml new file mode 100644 index 0000000000..1382b2aede --- /dev/null +++ b/dev/secrets.yml @@ -0,0 +1,3 @@ +IDENTITY_CLIENT_ID: !var dev/identity/app/client-id +IDENTITY_CLIENT_SECRET: !var dev/identity/app/client-secret +IDENTITY_PROVIDER_URI: !var dev/identity/app/provider-uri diff --git a/dev/start b/dev/start index 5a9461ace2..4fd7931b22 100755 --- a/dev/start +++ b/dev/start @@ -34,9 +34,11 @@ ENABLE_AUTHN_JWT=false ENABLE_AUTHN_LDAP=false ENABLE_AUTHN_OIDC=false ENABLE_OIDC_ADFS=false +ENABLE_OIDC_IDENTITY=false ENABLE_OIDC_KEYCLOAK=false ENABLE_OIDC_OKTA=false ENABLE_ROTATORS=false +IDENTITY_USER="" main() { unset COMPOSE_PROJECT_NAME @@ -93,7 +95,10 @@ Usage: start [options] authentication via: 'curl -X POST -d "alice" http://localhost:3000/authn-ldap/test/cucumber/alice/authenticate' -h, --help Shows this help message. + --identity-user Identity user to create in Conjur --oidc-adfs Adds to authn-oidc adfs static env configuration + --oidc-identity Starts with authn-oidc/identity as available authenticator. + Must be paired with --identity-user flag. --oidc-keycloak Starts with authn-oidc/keycloak and authn-oidc/keycloak2 as available authenticators. Service authn-oidc/keycloak uses AuthnOIDC V1 (based on ID token property validation), and @@ -117,7 +122,9 @@ parse_options() { --authn-jwt ) ENABLE_AUTHN_JWT=true ; shift ;; --authn-ldap ) ENABLE_AUTHN_LDAP=true ; shift ;; -h | --help ) print_help ; shift ;; + --identity-user ) IDENTITY_USER="$2" ; shift ; shift ;; --oidc-adfs ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_ADFS=true ; shift ;; + --oidc-identity ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_IDENTITY=true; shift ;; --oidc-keycloak ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_KEYCLOAK=true ; shift ;; --oidc-okta ) ENABLE_AUTHN_OIDC=true ; ENABLE_OIDC_OKTA=true ; shift ;; --rotators ) ENABLE_ROTATORS=true ; shift ;; @@ -130,6 +137,11 @@ parse_options() { fi ;; esac done + + if [[ $ENABLE_OIDC_IDENTITY = true && -z "$IDENTITY_USER" ]]; then + echo "Flag --oidc-identity must be paired with --identity-user. See --help." + exit 1 + fi } client_load_policy() { @@ -178,6 +190,10 @@ configure_oidc_authenticators() { if [[ $ENABLE_OIDC_ADFS = true ]]; then setup_adfs fi + + if [[ $ENABLE_OIDC_IDENTITY = true ]]; then + setup_identity + fi } setup_keycloak() { @@ -223,6 +239,17 @@ setup_adfs() { 'unique_name' 'ci/authn-oidc/policy_adfs.yml' } +setup_identity() { + policy_dir="policies/authenticators/authn-oidc" + rm -f "$policy_dir/identity-users.yml" + sed -e "s#{{ IDENTITY_USER }}#$IDENTITY_USER#g" "$policy_dir/identity-users.template.yml" > "$policy_dir/identity-users.yml" + + configure_oidc_v2 \ + 'identity' "$IDENTITY_PROVIDER_URI" \ + "$IDENTITY_CLIENT_ID" "$IDENTITY_CLIENT_SECRET" \ + 'email' +} + configure_oidc_v1() { service_id="$1" provider_uri="$2" @@ -268,6 +295,11 @@ enable_oidc_authenticators() { echo "Configuring ADFS as OpenID provider for manual testing" enabled_authenticators="$enabled_authenticators,authn-oidc/adfs" fi + + if [[ $ENABLE_OIDC_IDENTITY = true ]]; then + echo "Configuring Identity as OpenID provider for manual testing" + enabled_authenticators="$enabled_authenticators,authn-oidc/identity" + fi } init_data_key() { From 8bd755f4f96c27ca1b936d9f63e2af87e689561d Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Thu, 20 Apr 2023 10:09:23 -0400 Subject: [PATCH 17/42] Fail fast when missing required envvars --- dev/start | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/dev/start b/dev/start index 4fd7931b22..325cecdb47 100755 --- a/dev/start +++ b/dev/start @@ -40,10 +40,16 @@ ENABLE_OIDC_OKTA=false ENABLE_ROTATORS=false IDENTITY_USER="" +declare -A required_envvars +required_envvars[identity]="IDENTITY_CLIENT_ID IDENTITY_CLIENT_SECRET IDENTITY_PROVIDER_URI" +required_envvars[azure]="AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID AZURE_RESOURCE_GROUP" + main() { unset COMPOSE_PROJECT_NAME parse_options "$@" + check_env_vars + if ! docker info >/dev/null 2>&1; then echo "Docker does not seem to be running, run it first and retry" exit 1 @@ -144,6 +150,31 @@ parse_options() { fi } +check_env_vars() { + envvars="" + + if [[ $ENABLE_OIDC_IDENTITY = true ]]; then + envvars="$envvars ${required_envvars[identity]}" + fi + if [[ $ENABLE_AUTHN_AZURE = true ]]; then + envvars="$envvars ${required_envvars[azure]}" + fi + + IFS=' ' read -r -a envvars <<< "$envvars" + + envvar_message="Required environment variables not set:" + for envvar in "${envvars[@]}"; do + if [[ -z "${!envvar}" ]]; then + envvar_message="$envvar_message $envvar" + fi + done + + if [[ "$envvar_message" =~ .*"IDENTITY".* ]]; then + echo "$envvar_message" + exit 1 + fi +} + client_load_policy() { local policy_file=$1 From ae9cf9bdc7afa59b6369b851bd24bacaf98ea91d Mon Sep 17 00:00:00 2001 From: Rob Pothier Date: Fri, 31 Mar 2023 10:42:59 -0400 Subject: [PATCH 18/42] Adds checking pod logs on error --- .../authenticators_k8s/dev/Dockerfile.test | 1 + .../authenticators_k8s/test_gke_entrypoint.sh | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/ci/test_suites/authenticators_k8s/dev/Dockerfile.test b/ci/test_suites/authenticators_k8s/dev/Dockerfile.test index 50feb7cf5b..0faf393d7b 100644 --- a/ci/test_suites/authenticators_k8s/dev/Dockerfile.test +++ b/ci/test_suites/authenticators_k8s/dev/Dockerfile.test @@ -10,6 +10,7 @@ RUN apt-get update && \ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" && \ apt-get update && \ apt-get install -y docker-ce && \ + apt-get install -y jq && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh b/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh index a8b65168e6..d01e8f1d52 100755 --- a/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh +++ b/ci/test_suites/authenticators_k8s/test_gke_entrypoint.sh @@ -23,6 +23,13 @@ ENDOFLINE export LOCAL_DEV_VOLUME function finish { + # shellcheck disable=SC2181 + if [ $? -eq 0 ]; then + echo "Test PASSED!!!!" + else + echo "Test FAILED!!!! Displaying Kubernetes Resources" + dump_pod_logs + fi echo 'Finishing' echo '-----' @@ -97,6 +104,30 @@ function finish { delete_image "$NGINX_TAG" set -e } + +function get_pod_names(){ + # get a list of pods except for Conjur + kubectl get pods -o json \ + |jq -r '.items[].metadata.name' | grep -v conjur-authn-k8s +} + +function get_pod_container_names(){ + pod="${1}" + kubectl get "pod/${pod}" -o json \ + |jq -r '.spec.containers[].name' +} + +function dump_pod_logs(){ + kubectl get pods + get_pod_names | while read -r podname; do + get_pod_container_names "${podname}" | while read -r container_name; do + echo -e "\n\n ======= Container Logs Pod:${podname} Container:${container_name} =======" + kubectl logs "${podname}" --container "${container_name}" || true + echo -e " ======= End of Container Logs Pod:${podname} Container:${container_name} =======" + done + done +} + trap finish EXIT export TEMPLATE_TAG=gke. From bde3190aa4c4d8483ee5e8fd17643804b53e10b7 Mon Sep 17 00:00:00 2001 From: Matthew Felgate Date: Fri, 12 May 2023 10:18:27 -0400 Subject: [PATCH 19/42] Update the ttl to pt60m --- CHANGELOG.md | 6 ++++++ .../authn_oidc/v2/data_objects/authenticator.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e7fe7c5e6..eb1add184c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Nothing should go in this section, please add to the latest unreleased version (and update the corresponding date), or add a new version. +## [1.19.4] - 2023-05-12 + +### Changed +- OIDC tokens will now have a default ttl of 60 mins + [cyberark/conjur#2800](https://github.com/cyberark/conjur/pull/2800) + ## [1.19.3] - 2023-04-17 ### Added diff --git a/app/domain/authentication/authn_oidc/v2/data_objects/authenticator.rb b/app/domain/authentication/authn_oidc/v2/data_objects/authenticator.rb index a5c3d661e2..15f4bdffe5 100644 --- a/app/domain/authentication/authn_oidc/v2/data_objects/authenticator.rb +++ b/app/domain/authentication/authn_oidc/v2/data_objects/authenticator.rb @@ -29,7 +29,7 @@ def initialize( name: nil, response_type: 'code', provider_scope: nil, - token_ttl: 'PT8M' + token_ttl: 'PT60M' ) @account = account @provider_uri = provider_uri From 719ab778f33c1ac57022b12e19ce2e694a76a1b2 Mon Sep 17 00:00:00 2001 From: Matthew Felgate Date: Fri, 12 May 2023 10:20:55 -0400 Subject: [PATCH 20/42] Update cucumber test of increase of defualt ttl --- cucumber/authenticators_oidc/features/authn_oidc_v2.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber/authenticators_oidc/features/authn_oidc_v2.feature b/cucumber/authenticators_oidc/features/authn_oidc_v2.feature index d59053e6cb..a0e258f2fb 100644 --- a/cucumber/authenticators_oidc/features/authn_oidc_v2.feature +++ b/cucumber/authenticators_oidc/features/authn_oidc_v2.feature @@ -100,7 +100,7 @@ Feature: OIDC Authenticator V2 - Users can authenticate with OIDC authenticator And I fetch a code for username "alice" and password "alice" from "keycloak2" And I save my place in the audit log file And I authenticate via OIDC V2 with code and service-id "keycloak2" - Then user "alice" has been authorized by Conjur for 8 minutes + Then user "alice" has been authorized by Conjur for 60 minutes And I successfully GET "/secrets/cucumber/variable/test-variable" with authorized user And The following appears in the audit log after my savepoint: """ From c1e669f2f3a7023f92bf16e62a8bf16d0d1ce9ef Mon Sep 17 00:00:00 2001 From: Matthew Felgate Date: Mon, 15 May 2023 16:38:49 -0400 Subject: [PATCH 21/42] Log docker and rhel version in jenkins pipeline --- Jenkinsfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 5c8d83e4ba..38cd2f70ff 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -286,6 +286,8 @@ pipeline { agent { label 'executor-v2-rhel-ee' } steps { + sh(script: 'cat /etc/os-release', label: 'RHEL version') + sh(script: 'docker --version', label: 'Docker version') unstash 'version_info' // Catch errors so remaining steps always run. catchError { @@ -362,6 +364,8 @@ pipeline { } steps { + sh(script: 'cat /etc/os-release', label: 'RHEL version') + sh(script: 'docker --version', label: 'Docker version') runConjurTests(params.RUN_ONLY) } } From a1f821f2abd94188b5d5b4394b930d190942d7c0 Mon Sep 17 00:00:00 2001 From: Kate MacInnis Date: Tue, 16 May 2023 10:21:30 -0600 Subject: [PATCH 22/42] Upgrade bundler to 2.2.33 --- CHANGELOG.md | 6 ++++++ Dockerfile.fpm | 2 +- ci/coverage-report-generator/Gemfile.lock | 2 +- ci/coverage-report-generator/run.sh | 2 +- docs/Dockerfile | 2 +- gems/policy-parser/Dockerfile.test | 2 +- gems/policy-parser/conjur-policy-parser.gemspec | 2 +- 7 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb1add184c..4ced37844a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Nothing should go in this section, please add to the latest unreleased version (and update the corresponding date), or add a new version. +## [1.19.5] - 2023-05-16 + +### Security +- Update bundler to 2.2.33 to remove CVE-2021-43809 + [cyberark/conjur#2804](https://github.com/cyberark/conjur/pull/2804/files) + ## [1.19.4] - 2023-05-12 ### Changed diff --git a/Dockerfile.fpm b/Dockerfile.fpm index c0a3c6cb9e..ca25aa6995 100644 --- a/Dockerfile.fpm +++ b/Dockerfile.fpm @@ -5,7 +5,7 @@ RUN apt-get update -y && \ apt-get install -y zlib1g-dev \ liblzma-dev -ENV BUNDLER_VERSION 2.2.30 +ENV BUNDLER_VERSION 2.2.33 RUN gem install --no-document bundler:$BUNDLER_VERSION fpm RUN mkdir -p /src/opt/conjur/project diff --git a/ci/coverage-report-generator/Gemfile.lock b/ci/coverage-report-generator/Gemfile.lock index 46c55ec7fd..73a8ef94c8 100644 --- a/ci/coverage-report-generator/Gemfile.lock +++ b/ci/coverage-report-generator/Gemfile.lock @@ -17,4 +17,4 @@ DEPENDENCIES simplecov_json_formatter (= 0.1.4) BUNDLED WITH - 2.2.30 + 2.2.33 diff --git a/ci/coverage-report-generator/run.sh b/ci/coverage-report-generator/run.sh index 93abbd17ea..81793ed096 100755 --- a/ci/coverage-report-generator/run.sh +++ b/ci/coverage-report-generator/run.sh @@ -7,7 +7,7 @@ set -xeu IMAGE="ruby:3.0" -BUNDLER_VERSION="2.2.30" +BUNDLER_VERSION="2.2.33" REPO_ROOT=$(git rev-parse --show-toplevel) diff --git a/docs/Dockerfile b/docs/Dockerfile index 5eef693a5d..fa474d1f2f 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -2,7 +2,7 @@ FROM jekyll/jekyll:4.0 ADD Gemfile Gemfile.lock /srv/jekyll/ -ENV BUNDLER_VERSION 2.2.30 +ENV BUNDLER_VERSION 2.2.33 RUN gem install bundler -v $BUNDLER_VERSION RUN bundle --without development diff --git a/gems/policy-parser/Dockerfile.test b/gems/policy-parser/Dockerfile.test index 9b7d802e50..c5ac281ed0 100644 --- a/gems/policy-parser/Dockerfile.test +++ b/gems/policy-parser/Dockerfile.test @@ -8,6 +8,6 @@ COPY conjur-policy-parser.gemspec conjur-policy-parser.gemspec COPY lib/conjur-policy-parser-version.rb lib/conjur-policy-parser-version.rb # Make sure the expected version of Bundler is available -ENV BUNDLER_VERSION=2.2.30 +ENV BUNDLER_VERSION=2.2.33 RUN gem install bundler -v ${BUNDLER_VERSION} && \ bundle install diff --git a/gems/policy-parser/conjur-policy-parser.gemspec b/gems/policy-parser/conjur-policy-parser.gemspec index 2e8c5d09cd..f727996d7b 100644 --- a/gems/policy-parser/conjur-policy-parser.gemspec +++ b/gems/policy-parser/conjur-policy-parser.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |spec| spec.add_dependency("activesupport", ">= 4.2") spec.add_dependency("safe_yaml") - spec.add_development_dependency("bundler", "~> 2.2.30") + spec.add_development_dependency("bundler", "~> 2.2.33") spec.add_development_dependency("ci_reporter_rspec") spec.add_development_dependency("deepsort") spec.add_development_dependency("pry") From ebe3a8f54d9dd7f882ee8268508f247bb371db73 Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Wed, 3 May 2023 12:07:45 -0400 Subject: [PATCH 23/42] Fix dev env for AuthnJWT --- dev/start | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/start b/dev/start index 325cecdb47..68c5b22b34 100755 --- a/dev/start +++ b/dev/start @@ -125,7 +125,7 @@ parse_options() { --authn-azure ) ENABLE_AUTHN_AZURE=true ; shift ;; --authn-gcp ) ENABLE_AUTHN_GCP=true ; shift ;; --authn-iam ) ENABLE_AUTHN_IAM=true ; shift ;; - --authn-jwt ) ENABLE_AUTHN_JWT=true ; shift ;; + --authn-jwt ) ENABLE_AUTHN_JWT=true ; ENABLE_OIDC_KEYCLOAK=true ; shift ;; --authn-ldap ) ENABLE_AUTHN_LDAP=true ; shift ;; -h | --help ) print_help ; shift ;; --identity-user ) IDENTITY_USER="$2" ; shift ; shift ;; @@ -433,7 +433,8 @@ init_jwt() { # OIDC is a special case on JWT, JWT automation tests contain scenarios with # OIDC providers. - configure_oidc_providers + configure_oidc_authenticators + enable_oidc_authenticators echo "Configure jwks provider" docker-compose exec jwks "/tmp/create_nginx_certificate.sh" From 626e5a923528bd77250e72d372724ad095a32c3b Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Wed, 3 May 2023 13:53:00 -0400 Subject: [PATCH 24/42] AuthnJWT: support claims with hyphens --- CHANGELOG.md | 4 ++++ app/domain/authentication/authn_jwt/consts.rb | 2 +- .../features/authn_jwt_token_schema.feature | 4 ++-- .../authenticators_jwt/features/authn_status_jwt.feature | 2 +- .../authn-jwt/input_validation/parse_claim_aliases_spec.rb | 6 +++--- .../authn-jwt/input_validation/validate_claim_name_spec.rb | 3 +-- .../validate_restriction_name_spec.rb | 4 ++-- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ced37844a..c052b0f9d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - OIDC tokens will now have a default ttl of 60 mins [cyberark/conjur#2800](https://github.com/cyberark/conjur/pull/2800) +### Fixed +- AuthnJWT can now support claims that include hyphens. + [cyberark/conjur#2792](https://github.com/cyberark/conjur/pull/2792) + ## [1.19.3] - 2023-04-17 ### Added diff --git a/app/domain/authentication/authn_jwt/consts.rb b/app/domain/authentication/authn_jwt/consts.rb index b56cc9ae14..a8ea90e189 100644 --- a/app/domain/authentication/authn_jwt/consts.rb +++ b/app/domain/authentication/authn_jwt/consts.rb @@ -38,7 +38,7 @@ module AuthnJwt CLAIMS_CHARACTER_DELIMITER = "," TUPLE_CHARACTER_DELIMITER = ":" - PURE_CLAIM_NAME_REGEX = /[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*/.freeze + PURE_CLAIM_NAME_REGEX = /[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*/.freeze PURE_NESTED_CLAIM_NAME_REGEX = /^#{PURE_CLAIM_NAME_REGEX.source}(#{PATH_DELIMITER}#{PURE_CLAIM_NAME_REGEX.source})*$/.freeze SIGNING_KEY_RESOURCES_NAMES = [ diff --git a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature index 2aecc56f61..f63eec3c2c 100644 --- a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature +++ b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature @@ -700,7 +700,7 @@ Feature: JWT Authenticator - Token Schema Then the HTTP response status code is 401 And The following appears in the log after my savepoint: """ - CONJ00104E Failed to validate claim: claim name '%@^#[{]}$~=-+_?.><&^@*@#*sdhj812ehd' does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*)*$)'.> + CONJ00104E Failed to validate claim: claim name '%@^#[{]}$~=-+_?.><&^@*@#*sdhj812ehd' does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*)*$)'.> """ @negative @acceptance @@ -732,7 +732,7 @@ Feature: JWT Authenticator - Token Schema Then the HTTP response status code is 401 And The following appears in the log after my savepoint: """ - CONJ00104E Failed to validate claim: claim name '%@^#&^[{]}$~=-+_?.><812ehd' does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*)*$)'. + CONJ00104E Failed to validate claim: claim name '%@^#&^[{]}$~=-+_?.><812ehd' does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*)*$)'. """ @acceptance diff --git a/cucumber/authenticators_jwt/features/authn_status_jwt.feature b/cucumber/authenticators_jwt/features/authn_status_jwt.feature index 76e13f6071..b8dfbef350 100644 --- a/cucumber/authenticators_jwt/features/authn_status_jwt.feature +++ b/cucumber/authenticators_jwt/features/authn_status_jwt.feature @@ -1108,7 +1108,7 @@ Feature: JWT Authenticator - Status Check And I save my place in the log file When I GET "/authn-jwt/raw/cucumber/status" Then the HTTP response status code is 500 - And the authenticator status check fails with error "does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|0-9|.]*)*$)" + And the authenticator status check fails with error "does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|-|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|-|0-9|.]*)*$)" @negative @acceptance Scenario Outline: ONYX-10958: claim-aliases configured with invalid value, 500 Error diff --git a/spec/app/domain/authentication/authn-jwt/input_validation/parse_claim_aliases_spec.rb b/spec/app/domain/authentication/authn-jwt/input_validation/parse_claim_aliases_spec.rb index d365ed6448..82f6925d42 100644 --- a/spec/app/domain/authentication/authn-jwt/input_validation/parse_claim_aliases_spec.rb +++ b/spec/app/domain/authentication/authn-jwt/input_validation/parse_claim_aliases_spec.rb @@ -120,15 +120,15 @@ end end - context "When input has illegal - character in claim name" do + context "When input has legal - character in claim name" do subject do ::Authentication::AuthnJwt::InputValidation::ParseClaimAliases.new().call( claim_aliases: "my-claim:a" ) end - it "raises an error" do - expect { subject }.to raise_error(Errors::Authentication::AuthnJwt::ClaimAliasInvalidClaimFormat) + it "does not raise an error" do + expect { subject }.not_to raise_error end end diff --git a/spec/app/domain/authentication/authn-jwt/input_validation/validate_claim_name_spec.rb b/spec/app/domain/authentication/authn-jwt/input_validation/validate_claim_name_spec.rb index 8b8195a4e9..2bed04b6e5 100644 --- a/spec/app/domain/authentication/authn-jwt/input_validation/validate_claim_name_spec.rb +++ b/spec/app/domain/authentication/authn-jwt/input_validation/validate_claim_name_spec.rb @@ -28,7 +28,6 @@ "When claim name is 1 dot character '.'": [".", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When claim name is just 1 forbidden character '*'": ["*", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When claim name contains 1 forbidden character '*'": ["a*b", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], - "When claim name contains 1 forbidden character '-": ["a-b", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When claim name contains 1 forbidden character '%'": ["a%b", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When claim name contains 1 forbidden character '!'": ["a!b", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When claim name contains 1 forbidden character '('": ["a(b", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], @@ -44,7 +43,6 @@ "When claim name contains spaces": ["claim name", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When input has illegal [ character in claim name": ["my[claim", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When input has illegal [ ] characters in claim name": ["my[1]claim", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], - "When input has illegal - character in claim name": ["my-claim", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName], "When input has illegal : character in claim name": ["a:", Errors::Authentication::AuthnJwt::FailedToValidateClaimForbiddenClaimName] } @@ -53,6 +51,7 @@ "When claim name contains 1 allowed char 'f'": "f", "When claim name contains 1 allowed char '_'": "_", "When claim name contains value with allowed char '/'": "a/a", + "When claim name contains value with allowed char '-'": "a-b", "When claim name contains value with multiple allowed chars '/'": "a/a/a/a", "When claim name contains 1 allowed char '$'": "$", "When claim name contains digits in the middle": "$2w", diff --git a/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restriction_name_spec.rb b/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restriction_name_spec.rb index d724e340af..cfdd629ab3 100644 --- a/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restriction_name_spec.rb +++ b/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restriction_name_spec.rb @@ -19,6 +19,8 @@ Authentication::ResourceRestrictions::ResourceRestriction.new(name: "x.k8s", value: "val"), "annotation with _ in the name": Authentication::ResourceRestrictions::ResourceRestriction.new(name: "project_id", value: "val"), + "- in annotation": + Authentication::ResourceRestrictions::ResourceRestriction.new(name: "project-id", value: "val") } invalid_cases = { @@ -30,8 +32,6 @@ Authentication::ResourceRestrictions::ResourceRestriction.new(name: "a[2]/c", value: "val"), "Array element Access": Authentication::ResourceRestrictions::ResourceRestriction.new(name: "a/b/c[2]", value: "val"), - "- in annotation": - Authentication::ResourceRestrictions::ResourceRestriction.new(name: "project-id", value: "val"), ": in annotation": Authentication::ResourceRestrictions::ResourceRestriction.new(name: "project:id", value: "val") } From 4be2890e77ceb867a0bb12202de273dfbd98e26c Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Thu, 4 May 2023 15:07:53 -0400 Subject: [PATCH 25/42] AuthnJWT: support claims with inline namespaces --- CHANGELOG.md | 8 +-- .../identity_from_decoded_token_provider.rb | 11 +++- .../validate_restrictions_one_to_one.rb | 10 +++- .../features/authn_jwt_token_schema.feature | 36 +++++++++++++ ...entity_from_decoded_token_provider_spec.rb | 50 ++++++++++++++++--- .../validate_restrictions_one_to_one_spec.rb | 10 ++++ 6 files changed, 111 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c052b0f9d2..d7b9f74b83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,16 +15,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Update bundler to 2.2.33 to remove CVE-2021-43809 [cyberark/conjur#2804](https://github.com/cyberark/conjur/pull/2804/files) +### Fixed +- AuthnJWT now supports claims that include hyphens and inline namespaces. + [cyberark/conjur#2792](https://github.com/cyberark/conjur/pull/2792) + ## [1.19.4] - 2023-05-12 ### Changed - OIDC tokens will now have a default ttl of 60 mins [cyberark/conjur#2800](https://github.com/cyberark/conjur/pull/2800) -### Fixed -- AuthnJWT can now support claims that include hyphens. - [cyberark/conjur#2792](https://github.com/cyberark/conjur/pull/2792) - ## [1.19.3] - 2023-04-17 ### Added diff --git a/app/domain/authentication/authn_jwt/identity_providers/identity_from_decoded_token_provider.rb b/app/domain/authentication/authn_jwt/identity_providers/identity_from_decoded_token_provider.rb index 00d88bed32..90ace1b83b 100644 --- a/app/domain/authentication/authn_jwt/identity_providers/identity_from_decoded_token_provider.rb +++ b/app/domain/authentication/authn_jwt/identity_providers/identity_from_decoded_token_provider.rb @@ -85,7 +85,16 @@ def id_claim_key def id_claim_value return @id_claim_value if @id_claim_value - @id_claim_value = @jwt_authenticator_input.decoded_token.dig( + token = @jwt_authenticator_input.decoded_token + # Parsing the claim path means claims with slashes are interpreted + # as nested claims - for example 'a/b/c' corresponds to the doubly- + # nested claim: {"a":{"b":{"c":"value"}}}. + # + # We should also support claims that contain slashes as namespace + # indicators, such as 'namespace.com/claim', which would correspond + # to the top-level claim: {"namespace.com/claim":"value"}. + @id_claim_value = token[@id_claim_key] + @id_claim_value ||= token.dig( *parsed_claim_path ) end diff --git a/app/domain/authentication/authn_jwt/restriction_validation/validate_restrictions_one_to_one.rb b/app/domain/authentication/authn_jwt/restriction_validation/validate_restrictions_one_to_one.rb index 2c50291241..73474fa814 100644 --- a/app/domain/authentication/authn_jwt/restriction_validation/validate_restrictions_one_to_one.rb +++ b/app/domain/authentication/authn_jwt/restriction_validation/validate_restrictions_one_to_one.rb @@ -25,7 +25,15 @@ def valid_restriction?(restriction) raise Errors::Authentication::ResourceRestrictions::EmptyAnnotationGiven, annotation_name end - claim_value = @decoded_token.dig(*parsed_claim_path(claim_name)) + # Parsing the claim path means claims with slashes are interpreted + # as nested claims - for example 'a/b/c' corresponds to the doubly- + # nested claim: {"a":{"b":{"c":"value"}}}. + # + # We should also support claims that contain slashes as namespace + # indicators, such as 'namespace.com/claim', which would correspond + # to the top-level claim: {"namespace.com/claim":"value"}. + claim_value = @decoded_token[claim_name] + claim_value ||= @decoded_token.dig(*parsed_claim_path(claim_name)) if claim_value.nil? raise Errors::Authentication::AuthnJwt::JwtTokenClaimIsMissing, claim_name_for_error(annotation_name, claim_name) diff --git a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature index f63eec3c2c..a8c523707f 100644 --- a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature +++ b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature @@ -867,6 +867,42 @@ Feature: JWT Authenticator - Token Schema cucumber:host:myapp successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/raw """ + @sanity + @acceptance + Scenario: ONYX-29842 - Claims With In-Line Namespaces. Single enforced claim - 200 OK + Given I extend the policy with: + """ + - !variable conjur/authn-jwt/raw/enforced-claims + + - !host + id: myapp + annotations: + authn-jwt/raw/conjur.org/enforced-property: valid + + - !grant + role: !group conjur/authn-jwt/raw/hosts + member: !host myapp + """ + And I successfully set authn-jwt "enforced-claims" variable to value "conjur.org/enforced-property" + And I successfully set authn-jwt "token-app-property" variable to value "conjur.org/host-property" + And I add the secret value "test-secret" to the resource "cucumber:variable:test-variable" + And I permit host "myapp" to "execute" it + And I am using file "authn-jwt-token-schema" and alg "RS256" for remotely issue token: + """ + { + "conjur.org/enforced-property":"valid", + "conjur.org/host-property":"myapp" + } + """ + And I save my place in the log file + When I authenticate via authn-jwt with the JWT token + Then host "myapp" has been authorized by Conjur + And I successfully GET "/secrets/cucumber/variable/test-variable" with authorized user + And The following appears in the log after my savepoint: + """ + cucumber:host:myapp successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/raw + """ + @sanity @acceptance Scenario: ONYX-13716 Claim Alias nested annotation - 200 OK diff --git a/spec/app/domain/authentication/authn-jwt/identity_providers/identity_from_decoded_token_provider_spec.rb b/spec/app/domain/authentication/authn-jwt/identity_providers/identity_from_decoded_token_provider_spec.rb index c99cccedad..7fc1c8e6d1 100644 --- a/spec/app/domain/authentication/authn-jwt/identity_providers/identity_from_decoded_token_provider_spec.rb +++ b/spec/app/domain/authentication/authn-jwt/identity_providers/identity_from_decoded_token_provider_spec.rb @@ -12,6 +12,7 @@ let(:token_app_property_secret_value_is_hash) { 'nested' } let(:token_app_property_nested_from_hash_value) { 'nested/single' } let(:token_app_property_nested_from_array_value) { 'nested/array[0]' } + let(:token_app_property_namespaced) { 'namespaced.com/key' } let(:decoded_token) { { "namespace_id" => "1", @@ -36,7 +37,8 @@ "nested" => { "single" => "n_value", "array" => %w[a_value_1 a_value_2 a_value_3] - } + }, + "namespaced.com/key" => "namespaced-value" } } @@ -85,6 +87,12 @@ } } + let(:mocked_valid_secret_namespaced) { + { + "token-app-property" => token_app_property_namespaced + } + } + let(:mocked_valid_secrets_which_missing_in_token) { { "token-app-property" => "missing" @@ -98,13 +106,14 @@ let(:mocked_resource) { double("MockedResource") } let(:non_existing_field_name) { "non existing field name" } - let(:mocked_fetch_authenticator_secrets_exist_values) { double("MochedFetchAuthenticatorSecrets") } - let(:mocked_fetch_authenticator_secrets_value_points_to_array) { double("MochedFetchAuthenticatorSecretsPointsToArray") } - let(:mocked_fetch_authenticator_secrets_value_points_to_hash) { double("MochedFetchAuthenticatorSecretsPointsToHash") } - let(:mocked_fetch_authenticator_secrets_value_hash) { double("MochedFetchAuthenticatorSecretsHash") } - let(:mocked_fetch_authenticator_secrets_value_array) { double("MochedFetchAuthenticatorSecretsArray") } - let(:mocked_fetch_authenticator_secrets_which_missing_in_token) { double("MochedFetchAuthenticatorSecrets") } - let(:mocked_fetch_authenticator_secrets_empty_values) { double("MochedFetchAuthenticatorSecrets") } + let(:mocked_fetch_authenticator_secrets_exist_values) { double("MockedFetchAuthenticatorSecrets") } + let(:mocked_fetch_authenticator_secrets_value_points_to_array) { double("MockedFetchAuthenticatorSecretsPointsToArray") } + let(:mocked_fetch_authenticator_secrets_value_points_to_hash) { double("MockedFetchAuthenticatorSecretsPointsToHash") } + let(:mocked_fetch_authenticator_secrets_value_hash) { double("MockedFetchAuthenticatorSecretsHash") } + let(:mocked_fetch_authenticator_secrets_value_array) { double("MockedFetchAuthenticatorSecretsArray") } + let(:mocked_fetch_authenticator_secrets_value_namespaced) { double("MockedFetchAuthenticatorSecretsNamespaced") } + let(:mocked_fetch_authenticator_secrets_which_missing_in_token) { double("MockedFetchAuthenticatorSecrets") } + let(:mocked_fetch_authenticator_secrets_empty_values) { double("MockedFetchAuthenticatorSecrets") } let(:required_secret_missing_error) { "required secret missing error" } let(:required_identity_path_secret_missing_error) { "required secret missing error" } let(:mocked_fetch_required_secrets_token_app_with_value_identity_path_empty) { double("MockedFetchRequiredSecrets") } @@ -130,6 +139,11 @@ ::Authentication::AuthnJwt::PATH_DELIMITER + "a_value_1" } + let(:valid_jwt_identity_from_namespaced_claim) { + ::Authentication::AuthnJwt::IDENTITY_TYPE_HOST + + ::Authentication::AuthnJwt::PATH_DELIMITER + + "namespaced-value" + } let(:valid_jwt_identity_with_path) { ::Authentication::AuthnJwt::IDENTITY_TYPE_HOST + ::Authentication::AuthnJwt::PATH_DELIMITER + @@ -171,6 +185,10 @@ receive(:call).and_return(mocked_valid_secret_array) ) + allow(mocked_fetch_authenticator_secrets_value_namespaced).to( + receive(:call).and_return(mocked_valid_secret_namespaced) + ) + allow(mocked_fetch_authenticator_secrets_which_missing_in_token).to( receive(:call).and_return(mocked_valid_secrets_which_missing_in_token) ) @@ -360,6 +378,22 @@ end end + context "And 'identity-path' resource not exists, token-app-property with in-line namespace" do + subject do + ::Authentication::AuthnJwt::IdentityProviders::IdentityFromDecodedTokenProvider.new( + check_authenticator_secret_exists: mocked_authenticator_secret_exists, + fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_value_namespaced, + fetch_identity_path: mocked_fetch_identity_path_valid_empty_path + ).call( + jwt_authenticator_input: jwt_authenticator_input + ) + end + + it "jwt_identity returns host identity" do + expect(subject).to eql(valid_jwt_identity_from_namespaced_claim) + end + end + context "And 'identity-path' resource exists with value" do subject do ::Authentication::AuthnJwt::IdentityProviders::IdentityFromDecodedTokenProvider.new( diff --git a/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restrictions_one_to_one_spec.rb b/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restrictions_one_to_one_spec.rb index 3415ad9ac5..9cd505581d 100644 --- a/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restrictions_one_to_one_spec.rb +++ b/spec/app/domain/authentication/authn-jwt/restriction_validation/validate_restrictions_one_to_one_spec.rb @@ -11,6 +11,7 @@ let(:spaced_email) { " " } let(:right_login) { "cucumber" } let(:wrong_login) { "tomato" } + let(:namespaced_value) { "some-value" } let(:decoded_token) { { @@ -35,6 +36,7 @@ "team_name" => "myteam", "team_id" => "team76" }, + "namespaced/inline" => "some-value", "iat" => 1619352275, "nbf" => 1619352270, "exp" => 1619355875, @@ -77,6 +79,10 @@ Authentication::ResourceRestrictions::ResourceRestriction.new(name: "additional_data/namespace", value: wrong_email) } + let(:existing_namespaced_inline_restriction) { + Authentication::ResourceRestrictions::ResourceRestriction.new(name: "namespaced/inline", value: namespaced_value) + } + let(:empty_annotation_restriction) { Authentication::ResourceRestrictions::ResourceRestriction.new(name: "not_existing", value: "") } @@ -140,6 +146,10 @@ ) end + it "returns true when the restriction is for namespaced field and its value equals the token" do + expect(subject.valid_restriction?(existing_namespaced_inline_restriction)).to eql(true) + end + it "raises EmptyAnnotationGiven when annotation is empty" do expect { subject.valid_restriction?(empty_annotation_restriction) }.to raise_error(Errors::Authentication::ResourceRestrictions::EmptyAnnotationGiven) end From 85dce90bf91a1fc9216b2867c88ef00502705acb Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 18 May 2023 15:44:00 -0600 Subject: [PATCH 26/42] Adds support for authenticating with the AWS STS regional endpoint This commit: - Adds support for regional STS endpoints. - Improves log messaging for failed requests. - Adds unit tests for all authenticator functionality. --- CHANGELOG.md | 4 +- app/domain/authentication/authn_iam/Readme.md | 165 +++++++++++ .../authentication/authn_iam/authenticator.rb | 88 +++--- app/domain/errors.rb | 10 +- dev/start | 3 +- .../authn_iam/authenticator_spec.rb | 265 +++++++++++------- .../different-signing-request-url.yml | 50 ++++ .../authn-iam/expired-headers.yml | 50 ++++ .../global-sts-non-global-signer.yml | 50 ++++ .../invalid-signing-request-verb.yml | 50 ++++ ...onal-headers-signed-for-another-region.yml | 50 ++++ .../authn-iam/valid-global-headers.yml | 52 ++++ .../authn-iam/valid-regional-headers.yml | 52 ++++ .../authn-iam/verify-expired-headers.yml | 54 ---- 14 files changed, 742 insertions(+), 201 deletions(-) create mode 100644 app/domain/authentication/authn_iam/Readme.md create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/different-signing-request-url.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/expired-headers.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/global-sts-non-global-signer.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/invalid-signing-request-verb.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/regional-headers-signed-for-another-region.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-global-headers.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-regional-headers.yml delete mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-iam/verify-expired-headers.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d7b9f74b83..23a48a6f01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - AuthnJWT now supports claims that include hyphens and inline namespaces. [cyberark/conjur#2792](https://github.com/cyberark/conjur/pull/2792) +- Authn-IAM now uses the host in the signed headers to determine which STS endpoint + (global or regional) to use for validation. ## [1.19.4] - 2023-05-12 @@ -62,7 +64,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [cyberark/conjur#2739](https://github.com/cyberark/conjur/pull/2739) - Upgraded rack to v2.2.6.4 to resolve CVE-2023-27539 [cyberark/conjur#2750](https://github.com/cyberark/conjur/pull/2750) -- Updated nokogiri to 1.14.3 for CVE-2023-29469 and CVE-2023-28484 and rails to +- Updated nokogiri to 1.14.3 for CVE-2023-29469 and CVE-2023-28484 and rails to 6.1.7.3 for CVE-2023-28120 in Gemfile.lock, nokogiri to 1.1.4.3 for CVE-2023-29469 and commonmarker to 0.23.9 for CVE-2023-24824 and CVE-2023-26485 in docs/Gemfile.lock (all Medium severity issues flagged by Dependabot) diff --git a/app/domain/authentication/authn_iam/Readme.md b/app/domain/authentication/authn_iam/Readme.md new file mode 100644 index 0000000000..fd98fd41a4 --- /dev/null +++ b/app/domain/authentication/authn_iam/Readme.md @@ -0,0 +1,165 @@ +# AWS Authenticator + +This authenticator enables workloads running in AWS to authenticate with Conjur. + +## Policy + +The AWS Authenticator Policy follows the typical pattern for Authenticators. Please note, there are no required variables. + +### Authenticator Policy + +```yaml +# Applied to the root policy +- !policy + id: conjur + body: + - !policy + id: authn-iam + body: + - !policy + id: aws + body: + - !webservice + + - !group authenticatable + + - !permit + role: !group authenticatable + privilege: [ read, authenticate ] + resource: !webservice +``` + +### Host Policy + +```yaml +# Applied to the root policy +- !policy + id: aws + body: + - !policy + id: production + body: + - &hosts + - !host 188945769008/my_app_1 + - !host 188945769008/my-app-2 + - !host 188945769008/MyApp3 + + - !grant + members: *hosts + role: !group conjur/authn-iam/aws/authenticatable +``` + +### How IAM ARNs map to Conjur Roles + +The Conjur AWS Authenticator receives an AWS ARN as a result of the authorization request. Below is a sample: + +``` +arn:aws:sts::188945769008:assumed-role/conjur-role/i-08241b0e31fe23d20 +``` + +The interesting bits (from Conjur's perspective) are as follows: + +- `188945769008` - AWS account ID +- `conjur-role` - IAM role given to this workload + +All other elements or the AWS ARN are ignored by Conjur. + +- The Conjur Role ID must end with `188945769008/conjur-role` +- The Role can be located in a Conjur policy (ie. can have the prefix: `foo/bar/188945769008/conjur-role`) +- A Role can be either a User or a Host +- A Host can be in the Conjur `root` policy +- A User cannot be in the Conjur `root` policy + +## Authentication Workflow + +The authenticator works by passing the headers generated by an AWS signing request to the AWS STS's (Security Token Service) `GetCallerIdentity` endpoint. Conjur uses this signed service to exectute a call to AWS STS (on behalf of the workload we're authenticating). + +AWS STS has two options, global (`sts.amazonaws.com`), and regional (`sts..amazonaws.com`). Some important notes about using the STS endpoint. + +- If using the global endpoint (`sts.amazonaws.com`), the request must be signed using the `us-east-1` region. Signing a request using a different region will cause authentication to fail. +- If using the regional endpoint (preferred by AWS), the request must be signed by by that region. For example, if a request to `sts.eu-west-1.amazonaws.com`, it must be signed with the `eu-west-1` region. + +### Examples + +*All examples are in Ruby.* + +*All examples assume the AWS IAM role of the requestor is `my-app-2`* + +#### Valid Global Request + +```ruby +require 'aws-sigv4' +require 'aws-sdk' + +signed_aws_headers = Aws::Sigv4::Signer.new( + service: 'sts', + region: 'us-east-1', + credentials_provider: Aws::InstanceProfileCredentials.new +).sign_request( + http_method: 'GET', + url: 'https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15' +).headers +``` + +#### Valid Regional Request + +Any region can be used as long as the region is the same the target regional STS endpoint. + +```ruby +require 'aws-sigv4' +require 'aws-sdk' + +signed_aws_headers = Aws::Sigv4::Signer.new( + service: 'sts', + region: 'eu-west-1', + credentials_provider: Aws::InstanceProfileCredentials.new +).sign_request( + http_method: 'GET', + url: 'https://sts.eu-west-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15' +).headers +``` + +#### Retrieve a Conjur Authentication Token + +*Please note, the Ruby SDK does not support many of the authenticators via the SDK. The following is one example of how it might be handled.* + +```ruby +# Retrieve a Conjur authentication token +conjur_host = 'host/aws/production/188945769008/my-app-2' +conjur_url = 'conjur.mycompany.com' +conjur_account = 'demo' + +conjur_uri = URI("https://#{conjur_url}/authn-iam/aws/#{conjur_account}/#{ERB::Util.url_encode(conjur_host)}/authenticate") + +response = Net::HTTP.post_form(conjur_uri, signed_aws_headers) + +Conjur::API.new_from_token(response.body) +``` + +## Troubleshooting + + 1. *Error: CONJ00018E Invalid or expired AWS headers: Credential should be scoped to a valid region.* + + Request was signed by another region. If using the global endpoint, make sure the request was signed using `us-east-1`. If using the regional endpoint, make sure the regional signing request was signed with the corresponding region. + + 2. *Error: CONJ00018E Invalid or expired AWS headers: Signature expired: 20230518T152442Z is now earlier than 20230518T153438Z (20230518T154938Z - 15 min.)* + + The provided headers are no longer validate. Please regenerate the signing request and re-authenticate. + + 3. *Error: CONJ00018E Invalid or expired AWS headers: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.* + + The provided headers do not exactly match: + + ``` + GET https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + ``` + + or + + ``` + GET https://sts..amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + ``` + + - Verify the signing request uses 'GET' and not another HTTP verb. + - Verify the STS request includes the above parameters. + - If crafting your own signed request (ex. when using Powershell), verify your signed request headers against the above endpoints using a tool like Postman. diff --git a/app/domain/authentication/authn_iam/authenticator.rb b/app/domain/authentication/authn_iam/authenticator.rb index 50ffb454f6..5fab2f3c89 100755 --- a/app/domain/authentication/authn_iam/authenticator.rb +++ b/app/domain/authentication/authn_iam/authenticator.rb @@ -6,51 +6,38 @@ module Authentication module AuthnIam class Authenticator - def initialize(env:) + def initialize(env:, logger: Rails.logger, client: Net::HTTP) @env = env + @logger = logger + @client = client end def valid?(input) - signed_aws_headers = JSON.parse(input.credentials) # input.credentials is JSON holding the AWS signed headers + # input.credentials is JSON holding the AWS signed headers + signed_aws_headers = JSON.parse(input.credentials).transform_keys(&:downcase) + aws_response = response_from_signed_request(signed_aws_headers) - response_hash = identity_hash(response_from_signed_request(signed_aws_headers)) - trusted = response_hash != false - - trusted && iam_role_matches?(input.username, response_hash) - end - - def identity_hash(response) - Rails.logger.debug( - LogMessages::Authentication::AuthnIam::GetCallerIdentityBody.new( - response.body - ) + iam_role_matches?( + login: input.username, + aws_arn: aws_response[:arn], + aws_account: aws_response[:account] ) - - if response.code < 300 - Hash.from_xml(response.body) - else - Rails.logger.error( - Errors::Authentication::AuthnIam::IdentityVerificationErrorCode.new( - response.code - ) - ) - false - end end - def iam_role_matches?(login, response_hash) - split_assumed_role = response_hash["GetCallerIdentityResponse"]["GetCallerIdentityResult"]["Arn"].split(":") + private + # Parses STS Caller Identity response for the Conjur host and resolves it against the provided login + def iam_role_matches?(login:, aws_arn:, aws_account:) # removes the last 2 parts of login to be substituted by the info from getCallerIdentity - host_prefix = (login.split("/")[0..-3]).join("/") - aws_role_name = split_assumed_role[5].split("/")[1] - aws_account_id = response_hash["GetCallerIdentityResponse"]["GetCallerIdentityResult"]["Account"] - aws_user_id = response_hash["GetCallerIdentityResponse"]["GetCallerIdentityResult"]["UserId"] - host_to_match = "#{host_prefix}/#{aws_account_id}/#{aws_role_name}" + host_prefix = (login.split('/')[0..-3]).join('/') - Rails.logger.debug( + arn_parts = aws_arn.split(':') + aws_role_name = arn_parts[5].split('/')[1] + host_to_match = "#{host_prefix}/#{aws_account}/#{aws_role_name}" + + @logger.debug( LogMessages::Authentication::AuthnIam::AttemptToMatchHost.new( - aws_user_id, + login, host_to_match ) ) @@ -58,20 +45,37 @@ def iam_role_matches?(login, response_hash) login.eql?(host_to_match) end - def aws_signed_url - return 'https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15' + def extract_relevant_data(response) + { + arn: response.dig('GetCallerIdentityResponse', 'GetCallerIdentityResult', 'Arn'), + account: response.dig('GetCallerIdentityResponse', 'GetCallerIdentityResult', 'Account') + } end - def response_from_signed_request(aws_headers) - Rails.logger.debug(LogMessages::Authentication::AuthnIam::RetrieveIamIdentity.new) + # Call to AWS STS endpoint using the provided authentication header + def attempt_signed_request(signed_headers) + aws_request = URI("https://#{signed_headers['host']}/?Action=GetCallerIdentity&Version=2011-06-15") begin - RestClient.get(aws_signed_url, headers = aws_headers) - rescue RestClient::ExceptionWithResponse => e - Rails.logger.error(Errors::Authentication::AuthnIam::VerificationError.new(e.to_s)) - raise Errors::Authentication::AuthnIam::InvalidAWSHeaders, e.to_s + @client.get_response(aws_request, signed_headers) + + # Handle any network failures with a generic verification error + rescue StandardError => e + raise(Errors::Authentication::AuthnIam::VerificationError.new(e)) end end + + # Verify request with STS and handle response (happy or sad paths) + def response_from_signed_request(aws_headers) + response = attempt_signed_request(aws_headers) + body = Hash.from_xml(response.body) + + return extract_relevant_data(body) if response.code.to_i == 200 + + raise( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + body.dig('ErrorResponse', 'Error', 'Message').to_s.strip + ) + end end end end - diff --git a/app/domain/errors.rb b/app/domain/errors.rb index eb5ef49bd6..5018fe910f 100644 --- a/app/domain/errors.rb +++ b/app/domain/errors.rb @@ -270,20 +270,14 @@ module AuthnOidc module AuthnIam InvalidAWSHeaders = ::Util::TrackableErrorClass.new( - msg: "Invalid or expired AWS headers: {0}", + msg: "Invalid or expired AWS headers: {0-message}", code: "CONJ00018E" ) - VerificationError = ::Util::TrackableLogMessageClass.new( + VerificationError = ::Util::TrackableErrorClass.new( msg: "Verification of IAM identity failed with exception: {0-exception}", code: "CONJ00063E" ) - - IdentityVerificationErrorCode = ::Util::TrackableLogMessageClass.new( - msg: "Verification of IAM identity failed with HTTP code: {0-http-code}", - code: "CONJ00064E" - ) - end module AuthnK8s diff --git a/dev/start b/dev/start index 68c5b22b34..43433099d0 100755 --- a/dev/start +++ b/dev/start @@ -40,7 +40,7 @@ ENABLE_OIDC_OKTA=false ENABLE_ROTATORS=false IDENTITY_USER="" -declare -A required_envvars +declare -a required_envvars required_envvars[identity]="IDENTITY_CLIENT_ID IDENTITY_CLIENT_SECRET IDENTITY_PROVIDER_URI" required_envvars[azure]="AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID AZURE_RESOURCE_GROUP" @@ -72,6 +72,7 @@ main() { start_conjur_server init_ldap + init_iam init_azure init_gcp init_jwt diff --git a/spec/app/domain/authentication/authn_iam/authenticator_spec.rb b/spec/app/domain/authentication/authn_iam/authenticator_spec.rb index 97d886b05a..0eadf4f528 100644 --- a/spec/app/domain/authentication/authn_iam/authenticator_spec.rb +++ b/spec/app/domain/authentication/authn_iam/authenticator_spec.rb @@ -3,103 +3,178 @@ require 'spec_helper' RSpec.describe(Authentication::AuthnIam::Authenticator) do - def expired_aws_headers - "{\"host\":\"sts.amazonaws.com\",\"x-amz-date\":\"20180620T025910Z\","\ - "\"x-amz-security-token\":\"FQoDYXdzEPv//////////wEaDHwvkDqh5pHmZNe5hSK3AzevmnHjzweG6m1in"\ - "/CQ8NB7PCY0nTtWsCXLU5FsHmOoXs6KgVOu8ucghebak4b/iaDCpSprH3GPjLcNatywkUEQqX8rQKy2DoKMy7ZMHNT1ivhEn "\ - "vE3HR0GPkkGGWYhLTTrQDdI5fBcb3yJ /TyrcmUuBTKXwQJmvcnDe505SPpuSZm7tdrDX5SpItMngqGcrRhCjuprpk5nPVwSQ"\ - "q6usp7hJYPmu/6u9eVP3rQ TFPldhRvRxu5rcssURdrIwbjMugZQff/8XERxyxPrTkJQekcqMvvV6gexDZcBOS1JtIsKfJEXU"\ - "mK3kwV4liQsUevxyanWMc4jT0tiBkDj2 nvXUFt6dejppdTTRdEtBXg5xZUrGDCQDUU9eBgydoTLGav9rWiM7bWtpP4A1m0E9"\ - "LoX47FScSDkqk0Hy6Dr9jzhb4HOodlgaldTs8BNlgN9xXgACdacdPqnhaYLCgAWsaUZPKuZmdyH96F59rcrVscf456ivXTrXp"\ - "t6pL1ZQyRCc04hkovErvv1L2CwEaGAc k0bvbq0pbzTftTh7 9xY3pFxbL AALoR0t2/CfhyomvoG72Cl/nvAo7 "\ - "m2QU\",\"x-amz-content-sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b"\ - "855\",\"authorization\":\"AWS4-HMAC-SHA256 Credential=ASIAJJTVXJS5KDKXKNPQ/20180620/us-east-1/sts/aw"\ - "s4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=230fa"\ - "38a232969747b77e82f6c845f63941ebde89eb2cc20ed1c6f2dbabc92b6\"}" - end - - def valid_response - double('HTTPResponse', - code: 200, - body: %( - - - arn:aws:sts::011915987442:assumed-role/MyApp/i-0a5702a5a078e1a00 - AROAIYXQMEFIAVEOFMW5Y:i-0a5702a5a078e1a00 - 011915987442 - - - f555066a-7417-11e8-8ded-8daed431985e - - + let(:authenticator) { Authentication::AuthnIam::Authenticator.new(env:[]) } + let(:conjur_role) { 'host/foo/188945769008/conjur-role' } + + # Good headers + let(:valid_global_headers) { '{"host":"sts.amazonaws.com","x-amz-date":"20230518T152525Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=81b929060b45f05470c9f542a9e46cdce51d37c1d22a58d1942b7fa175079af5"}' } + let(:valid_regional_headers) { '{"host":"sts.eu-central-1.amazonaws.com","x-amz-date":"20230518T152442Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/eu-central-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=8e0bebec9a3ce860b4595a4b27710da558a157a711e2dcbfe3a86881af99c459"}' } + + # Bad headers + let(:expired_headers) { '{"host":"sts.eu-central-1.amazonaws.com","x-amz-date":"20230518T152442Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/eu-central-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=8e0bebec9a3ce860b4595a4b27710da558a157a711e2dcbfe3a86881af99c459"}' } + let(:different_signing_request_uri) { '{"host":"sts.amazonaws.com","x-amz-date":"20230518T153130Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=2f0162e0124dfeb105bc8a318efb93272797e2762a4fe93010437594a0d0244d"}' } + let(:different_signing_request_verb) { '{"host":"sts.amazonaws.com","x-amz-date":"20230518T153042Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=bd7f1e549999b6854adfb7c35e344efa38d74bac1c9078fbc34f71f4ff90173b"}' } + let(:global_non_global_signer) { '{"host":"sts.amazonaws.com","x-amz-date":"20230518T155824Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDgaDGV1LWNlbnRyYWwtMSJIMEYCIQDQLBDLt5kNEEj40A2gX/kurzw9AAwYKnJIjQSrXGynmQIhAINJPoMDfHiSe6Bjzuwc9lwbe/iUPkVUUClFbUicPhNtKrwFCGEQAxoMMTg4OTQ1NzY5MDA4IgyYkP5L6wWxumObWPQqmQXd1mkF8hU1CCkhdJdc73vLVnGFvGbqru9SpzDIkbo0/syIZR7pjEoPTw/sUxFa/jYgcRrDh9bUmTBT7zU2/HDJRrwZfNgu9PPEtRGkIUOYri8muc0X8yLnHlk/5jvpwU5RY2uUoTZt+pvgm8jOHi/lkrtPx8uiQeEOeBkKe/DA2tFfHeVrC9OPkWQkjm0k9nsDggpwy9jf+RbzeSRb6Tyg4WWplDKW+a7VhBpBs1cNGGx9um590gpgpxaC93CIAtxI+iOxreH+xofhrJAPirms1yR4f5GD+glhr/mpCdclX0Eehvb+nxosnYKMh8XvlKR1GzP/PtqGCCRMpCByPmiXtotOMEQv96QGGs0/A8vdiktjJuGbjSQxKvw1UNG5Cxrb7DRqexPoILxoZAICSiFDK2vPPl2ePTWrk3MFxBKj+UK2VihhE1fpnZ7UXrVmQAUzNtDTdaaTcWy2ZTf4oAcRkUsYUl1BOIQYEcI0LmpCkqHb51ANbPO9bFxLAGTUuV9AMSRcrEojiFlxl+yiK5lPygJzrbRQBhnh3srxoHjfN5KvgVf0PqS3HUWIX/eknhBTJbhPO9d7me1/rTudqFd1dLEEiTJbN6KGF0vZvAgnahcoA4YSxLhG/EkNdOKbS/lJOUeysN/l/3L19RuWX9gd2Pc2FD7KWM6mzNAFIi8OAIChTnhZO7a6lcYZb+5uY+5N3Oh2Qthx7cc5k0DGQXX2FGYQgQKY9MWQo6s3Z2DwfNDddgYEM2clnnNPP+lNU7evdCsDb4/QPyDv+l14Tmdz2adhcsi4hkX9YGaCko6S6tdPI1fURyTkCKfUJ643ZNXyqmx4vRPupO2ukJArh7piCas8+B4FsScjD1sD3dH9aVwa2sI1tVed9zCclpmjBjqwATqNRvOZinA+mqThE4YjTVliRSaqNG6UsCq/x3f6R5/KBMacp4f0nZuXTOfvNgiFHju/m1paGf8JwylAkKummhneSOoZAbQ16dQhDu3ejZydbj5nRkTC/1VT87SFf+S+k66J8ycfIs2nkwlIvHWo+TbD36fBcTNq69BtAvluRRIH77zXg60zBK5KmmtKUbeayHVZngjZt/u3ezrRGuLu9TUCYtWMY0VVKyYUX36MykWY","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGFOUEXPF/20230518/eu-north-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=e643e2bb5d737954951f34ff67c4a11e00d022b402579f85ff9d99a5f70cbc53"}' } + let(:regional_headers_signed_for_another_region) { '{"host":"sts.us-west-1.amazonaws.com","x-amz-date":"20230518T160804Z","x-amz-security-token":"IQoJb3JpZ2luX2VjEDgaDGV1LWNlbnRyYWwtMSJIMEYCIQDQLBDLt5kNEEj40A2gX/kurzw9AAwYKnJIjQSrXGynmQIhAINJPoMDfHiSe6Bjzuwc9lwbe/iUPkVUUClFbUicPhNtKrwFCGEQAxoMMTg4OTQ1NzY5MDA4IgyYkP5L6wWxumObWPQqmQXd1mkF8hU1CCkhdJdc73vLVnGFvGbqru9SpzDIkbo0/syIZR7pjEoPTw/sUxFa/jYgcRrDh9bUmTBT7zU2/HDJRrwZfNgu9PPEtRGkIUOYri8muc0X8yLnHlk/5jvpwU5RY2uUoTZt+pvgm8jOHi/lkrtPx8uiQeEOeBkKe/DA2tFfHeVrC9OPkWQkjm0k9nsDggpwy9jf+RbzeSRb6Tyg4WWplDKW+a7VhBpBs1cNGGx9um590gpgpxaC93CIAtxI+iOxreH+xofhrJAPirms1yR4f5GD+glhr/mpCdclX0Eehvb+nxosnYKMh8XvlKR1GzP/PtqGCCRMpCByPmiXtotOMEQv96QGGs0/A8vdiktjJuGbjSQxKvw1UNG5Cxrb7DRqexPoILxoZAICSiFDK2vPPl2ePTWrk3MFxBKj+UK2VihhE1fpnZ7UXrVmQAUzNtDTdaaTcWy2ZTf4oAcRkUsYUl1BOIQYEcI0LmpCkqHb51ANbPO9bFxLAGTUuV9AMSRcrEojiFlxl+yiK5lPygJzrbRQBhnh3srxoHjfN5KvgVf0PqS3HUWIX/eknhBTJbhPO9d7me1/rTudqFd1dLEEiTJbN6KGF0vZvAgnahcoA4YSxLhG/EkNdOKbS/lJOUeysN/l/3L19RuWX9gd2Pc2FD7KWM6mzNAFIi8OAIChTnhZO7a6lcYZb+5uY+5N3Oh2Qthx7cc5k0DGQXX2FGYQgQKY9MWQo6s3Z2DwfNDddgYEM2clnnNPP+lNU7evdCsDb4/QPyDv+l14Tmdz2adhcsi4hkX9YGaCko6S6tdPI1fURyTkCKfUJ643ZNXyqmx4vRPupO2ukJArh7piCas8+B4FsScjD1sD3dH9aVwa2sI1tVed9zCclpmjBjqwATqNRvOZinA+mqThE4YjTVliRSaqNG6UsCq/x3f6R5/KBMacp4f0nZuXTOfvNgiFHju/m1paGf8JwylAkKummhneSOoZAbQ16dQhDu3ejZydbj5nRkTC/1VT87SFf+S+k66J8ycfIs2nkwlIvHWo+TbD36fBcTNq69BtAvluRRIH77zXg60zBK5KmmtKUbeayHVZngjZt/u3ezrRGuLu9TUCYtWMY0VVKyYUX36MykWY","x-amz-content-sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","authorization":"AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGFOUEXPF/20230518/eu-north-1/sts/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=bfaefe50abefa68b0081af52687885a7391006f2c8b0d80b6c20beb7da808d56"}' } + + describe '.valid?' do + context 'headers are valid' do + context 'when using the global STS endpoint' do + context 'with request signed by `us-east-1`' do + let(:payload) do + double('AuthenticationParameters', credentials: valid_global_headers, username: conjur_role) + end + it 'succeeds', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(true) + end + end + context 'with request signed for a non `us-east-1` region' do + let(:payload) do + double('AuthenticationParameters', credentials: global_non_global_signer, username: conjur_role) + end + it 'fails', vcr: 'authenticators/authn-iam/global-sts-non-global-signer' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + 'CONJ00018E Invalid or expired AWS headers: Credential should be scoped to a valid region.' + ) + end + end + end + context 'when using the regional STS endpoint' do + context 'when regional endpoint request was signed for that region' do + let(:payload) do + double('AuthenticationParameters', credentials: valid_regional_headers, username: conjur_role) + end + it 'succeeds', vcr: 'authenticators/authn-iam/valid-regional-headers' do + expect(authenticator.valid?(payload)).to be(true) + end + end + context 'when regional endpoint request was signed for another region' do + let(:payload) do + double('AuthenticationParameters', credentials: regional_headers_signed_for_another_region, username: conjur_role) + end + it 'fails', vcr: 'authenticators/authn-iam/regional-headers-signed-for-another-region' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + 'CONJ00018E Invalid or expired AWS headers: Credential should be scoped to a valid region.' + ) + end + end + end + end + context 'when headers are invalid' do + context 'when headers have expired' do + let(:payload) do + double('AuthenticationParameters', credentials: expired_headers, username: conjur_role) + end + it 'fails with exception', vcr: 'authenticators/authn-iam/expired-headers' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + 'CONJ00018E Invalid or expired AWS headers: Signature expired: 20230518T152442Z is now earlier than 20230518T153438Z (20230518T154938Z - 15 min.)' ) - ) - end - - def invalid_response - double('HTTPResponse', - code: 404, - body: "Error" - ) - end - - def valid_login - "host/myapp/011915987442/MyApp" - end - - def invalid_login - "host/myapp/InvalidAccount/InvalidRole" - end - - let (:authenticator_instance) do - Authentication::AuthnIam::Authenticator.new(env:[]) - end - - it "valid? with expired AWS headers", vcr: 'authenticators/authn-iam/verify-expired-headers' do - subject = authenticator_instance - parameters = double('AuthenticationParameters', credentials: expired_aws_headers) - expect{subject.valid?(parameters)}.to( - raise_error(Errors::Authentication::AuthnIam::InvalidAWSHeaders) - ) - end - - it "validates identity_hash with valid response" do - subject = authenticator_instance - expect { subject.identity_hash(valid_response) }.to_not raise_error - - expect(subject.identity_hash(valid_response)).to have_key("GetCallerIdentityResponse") - - expected = { - "GetCallerIdentityResponse" => a_hash_including( - "GetCallerIdentityResult" => a_hash_including( - "Arn" => "arn:aws:sts::011915987442:assumed-role/MyApp/i-0a5702a5a078e1a00", - "UserId" => anything, - "Account" => anything - ) + end + end + context 'for the signing request' do + context 'when the verb is not GET' do + let(:payload) do + double('AuthenticationParameters', credentials: different_signing_request_verb, username: conjur_role) + end + it 'fails with exception', vcr: 'authenticators/authn-iam/invalid-signing-request-verb' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + 'CONJ00018E Invalid or expired AWS headers: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.' + ) + end + end + context 'when the signed URI is different' do + let(:payload) do + double('AuthenticationParameters', credentials: different_signing_request_uri, username: conjur_role) + end + it 'fails', vcr: 'authenticators/authn-iam/different-signing-request-url' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::InvalidAWSHeaders, + 'CONJ00018E Invalid or expired AWS headers: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.' + ) + end + end + end + end + context 'when an http exception occurs' do + let(:authenticator) do + Authentication::AuthnIam::Authenticator.new( + env: [], + client: class_double(Net::HTTP).tap do |double| + allow(double).to receive(:get_response).and_raise(Timeout::Error) + end ) - } - - expect(subject.identity_hash(valid_response)).to include(expected) - expect(subject.identity_hash(valid_response)) - end - - it "validates identity_hash with invalid response" do - subject = authenticator_instance - expect(subject.identity_hash(invalid_response)).to eq(false) - end - - it "matches valid login to AWS IAM role (based on AWS response)" do - subject = authenticator_instance - identity_hash = subject.identity_hash(valid_response) - - expect(subject.iam_role_matches?(valid_login, identity_hash)).to eq(true) - expect(subject.iam_role_matches?(invalid_login, identity_hash)).to eq(false) + end + let(:payload) do + double('AuthenticationParameters', credentials: valid_global_headers, username: conjur_role) + end + it 'fails' do + expect { authenticator.valid?(payload) } + .to raise_error( + Errors::Authentication::AuthnIam::VerificationError, + 'CONJ00063E Verification of IAM identity failed with exception: Timeout::Error' + ) + end + end end - - it "fails invalid login with AWS IAM role (based on AWS response)" do - subject = authenticator_instance - identity_hash = subject.identity_hash(valid_response) - - expect(subject.iam_role_matches?(invalid_login, identity_hash)).to eq(false) + context 'for different roles' do + context 'when login is a User' do + let(:payload) do + double('AuthenticationParameters', username: 'foo/bar/baz/188945769008/conjur-role', credentials: valid_global_headers) + end + it 'succeeds', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(true) + end + context 'when login is in the root policy' do + let(:payload) do + double('AuthenticationParameters', username: '188945769008/conjur-role', credentials: valid_global_headers) + end + it 'fails', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(false) + end + end + end + context 'when login is a host' do + context 'when role has multiple policy nestings' do + let(:payload) do + double('AuthenticationParameters', username: 'host/foo/bar/baz/188945769008/conjur-role', credentials: valid_global_headers) + end + it 'succeeds', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(true) + end + end + context 'when account-id is missing from username' do + let(:payload) do + double('AuthenticationParameters', username: 'host/foo/bar/baz/conjur-role', credentials: valid_global_headers) + end + it 'fails', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(false) + end + end + context 'when login does not include an AWS resource id' do + let(:payload) do + double('AuthenticationParameters', username: 'host/foo/188945769008', credentials: valid_global_headers) + end + it 'fails', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(false) + end + end + context 'when login is in the root policy' do + let(:payload) do + double('AuthenticationParameters', username: 'host/188945769008/conjur-role', credentials: valid_global_headers) + end + it 'succeeds', vcr: 'authenticators/authn-iam/valid-global-headers' do + expect(authenticator.valid?(payload)).to be(true) + end + end + end end end diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/different-signing-request-url.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/different-signing-request-url.yml new file mode 100644 index 0000000000..975a4f8311 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/different-signing-request-url.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T153130Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=2f0162e0124dfeb105bc8a318efb93272797e2762a4fe93010437594a0d0244d + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 403 + message: Forbidden + headers: + X-Amzn-Requestid: + - 616d2ad4-7fc4-4188-acfa-ecc9cbfbc366 + Content-Type: + - text/xml + Content-Length: + - '431' + Date: + - Thu, 18 May 2023 15:35:06 GMT + body: + encoding: UTF-8 + string: | + + + Sender + SignatureDoesNotMatch + The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. + + 616d2ad4-7fc4-4188-acfa-ecc9cbfbc366 + + recorded_at: Thu, 18 May 2023 15:35:06 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/expired-headers.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/expired-headers.yml new file mode 100644 index 0000000000..f20e5868b9 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/expired-headers.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.eu-central-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T152442Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/eu-central-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=8e0bebec9a3ce860b4595a4b27710da558a157a711e2dcbfe3a86881af99c459 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 403 + message: Forbidden + headers: + X-Amzn-Requestid: + - 7b86b01a-232e-417b-b8dd-f5f99253957e + Content-Type: + - text/xml + Content-Length: + - '354' + Date: + - Thu, 18 May 2023 15:49:37 GMT + body: + encoding: UTF-8 + string: | + + + Sender + SignatureDoesNotMatch + Signature expired: 20230518T152442Z is now earlier than 20230518T153438Z (20230518T154938Z - 15 min.) + + 7b86b01a-232e-417b-b8dd-f5f99253957e + + recorded_at: Thu, 18 May 2023 15:49:38 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/global-sts-non-global-signer.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/global-sts-non-global-signer.yml new file mode 100644 index 0000000000..a03c5e55bb --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/global-sts-non-global-signer.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T155824Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDgaDGV1LWNlbnRyYWwtMSJIMEYCIQDQLBDLt5kNEEj40A2gX/kurzw9AAwYKnJIjQSrXGynmQIhAINJPoMDfHiSe6Bjzuwc9lwbe/iUPkVUUClFbUicPhNtKrwFCGEQAxoMMTg4OTQ1NzY5MDA4IgyYkP5L6wWxumObWPQqmQXd1mkF8hU1CCkhdJdc73vLVnGFvGbqru9SpzDIkbo0/syIZR7pjEoPTw/sUxFa/jYgcRrDh9bUmTBT7zU2/HDJRrwZfNgu9PPEtRGkIUOYri8muc0X8yLnHlk/5jvpwU5RY2uUoTZt+pvgm8jOHi/lkrtPx8uiQeEOeBkKe/DA2tFfHeVrC9OPkWQkjm0k9nsDggpwy9jf+RbzeSRb6Tyg4WWplDKW+a7VhBpBs1cNGGx9um590gpgpxaC93CIAtxI+iOxreH+xofhrJAPirms1yR4f5GD+glhr/mpCdclX0Eehvb+nxosnYKMh8XvlKR1GzP/PtqGCCRMpCByPmiXtotOMEQv96QGGs0/A8vdiktjJuGbjSQxKvw1UNG5Cxrb7DRqexPoILxoZAICSiFDK2vPPl2ePTWrk3MFxBKj+UK2VihhE1fpnZ7UXrVmQAUzNtDTdaaTcWy2ZTf4oAcRkUsYUl1BOIQYEcI0LmpCkqHb51ANbPO9bFxLAGTUuV9AMSRcrEojiFlxl+yiK5lPygJzrbRQBhnh3srxoHjfN5KvgVf0PqS3HUWIX/eknhBTJbhPO9d7me1/rTudqFd1dLEEiTJbN6KGF0vZvAgnahcoA4YSxLhG/EkNdOKbS/lJOUeysN/l/3L19RuWX9gd2Pc2FD7KWM6mzNAFIi8OAIChTnhZO7a6lcYZb+5uY+5N3Oh2Qthx7cc5k0DGQXX2FGYQgQKY9MWQo6s3Z2DwfNDddgYEM2clnnNPP+lNU7evdCsDb4/QPyDv+l14Tmdz2adhcsi4hkX9YGaCko6S6tdPI1fURyTkCKfUJ643ZNXyqmx4vRPupO2ukJArh7piCas8+B4FsScjD1sD3dH9aVwa2sI1tVed9zCclpmjBjqwATqNRvOZinA+mqThE4YjTVliRSaqNG6UsCq/x3f6R5/KBMacp4f0nZuXTOfvNgiFHju/m1paGf8JwylAkKummhneSOoZAbQ16dQhDu3ejZydbj5nRkTC/1VT87SFf+S+k66J8ycfIs2nkwlIvHWo+TbD36fBcTNq69BtAvluRRIH77zXg60zBK5KmmtKUbeayHVZngjZt/u3ezrRGuLu9TUCYtWMY0VVKyYUX36MykWY + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGFOUEXPF/20230518/eu-north-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=e643e2bb5d737954951f34ff67c4a11e00d022b402579f85ff9d99a5f70cbc53 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 403 + message: Forbidden + headers: + X-Amzn-Requestid: + - dfaae187-a48e-4432-a1d2-f2267aed9ded + Content-Type: + - text/xml + Content-Length: + - '300' + Date: + - Thu, 18 May 2023 16:00:55 GMT + body: + encoding: UTF-8 + string: | + + + Sender + SignatureDoesNotMatch + Credential should be scoped to a valid region. + + dfaae187-a48e-4432-a1d2-f2267aed9ded + + recorded_at: Thu, 18 May 2023 16:00:55 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/invalid-signing-request-verb.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/invalid-signing-request-verb.yml new file mode 100644 index 0000000000..92e6d84c4e --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/invalid-signing-request-verb.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T153042Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=bd7f1e549999b6854adfb7c35e344efa38d74bac1c9078fbc34f71f4ff90173b + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 403 + message: Forbidden + headers: + X-Amzn-Requestid: + - a3285804-b289-4b2b-8138-d80cbdf6287f + Content-Type: + - text/xml + Content-Length: + - '431' + Date: + - Thu, 18 May 2023 15:35:05 GMT + body: + encoding: UTF-8 + string: | + + + Sender + SignatureDoesNotMatch + The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. + + a3285804-b289-4b2b-8138-d80cbdf6287f + + recorded_at: Thu, 18 May 2023 15:35:05 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/regional-headers-signed-for-another-region.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/regional-headers-signed-for-another-region.yml new file mode 100644 index 0000000000..91d709ffde --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/regional-headers-signed-for-another-region.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.us-west-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T160804Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDgaDGV1LWNlbnRyYWwtMSJIMEYCIQDQLBDLt5kNEEj40A2gX/kurzw9AAwYKnJIjQSrXGynmQIhAINJPoMDfHiSe6Bjzuwc9lwbe/iUPkVUUClFbUicPhNtKrwFCGEQAxoMMTg4OTQ1NzY5MDA4IgyYkP5L6wWxumObWPQqmQXd1mkF8hU1CCkhdJdc73vLVnGFvGbqru9SpzDIkbo0/syIZR7pjEoPTw/sUxFa/jYgcRrDh9bUmTBT7zU2/HDJRrwZfNgu9PPEtRGkIUOYri8muc0X8yLnHlk/5jvpwU5RY2uUoTZt+pvgm8jOHi/lkrtPx8uiQeEOeBkKe/DA2tFfHeVrC9OPkWQkjm0k9nsDggpwy9jf+RbzeSRb6Tyg4WWplDKW+a7VhBpBs1cNGGx9um590gpgpxaC93CIAtxI+iOxreH+xofhrJAPirms1yR4f5GD+glhr/mpCdclX0Eehvb+nxosnYKMh8XvlKR1GzP/PtqGCCRMpCByPmiXtotOMEQv96QGGs0/A8vdiktjJuGbjSQxKvw1UNG5Cxrb7DRqexPoILxoZAICSiFDK2vPPl2ePTWrk3MFxBKj+UK2VihhE1fpnZ7UXrVmQAUzNtDTdaaTcWy2ZTf4oAcRkUsYUl1BOIQYEcI0LmpCkqHb51ANbPO9bFxLAGTUuV9AMSRcrEojiFlxl+yiK5lPygJzrbRQBhnh3srxoHjfN5KvgVf0PqS3HUWIX/eknhBTJbhPO9d7me1/rTudqFd1dLEEiTJbN6KGF0vZvAgnahcoA4YSxLhG/EkNdOKbS/lJOUeysN/l/3L19RuWX9gd2Pc2FD7KWM6mzNAFIi8OAIChTnhZO7a6lcYZb+5uY+5N3Oh2Qthx7cc5k0DGQXX2FGYQgQKY9MWQo6s3Z2DwfNDddgYEM2clnnNPP+lNU7evdCsDb4/QPyDv+l14Tmdz2adhcsi4hkX9YGaCko6S6tdPI1fURyTkCKfUJ643ZNXyqmx4vRPupO2ukJArh7piCas8+B4FsScjD1sD3dH9aVwa2sI1tVed9zCclpmjBjqwATqNRvOZinA+mqThE4YjTVliRSaqNG6UsCq/x3f6R5/KBMacp4f0nZuXTOfvNgiFHju/m1paGf8JwylAkKummhneSOoZAbQ16dQhDu3ejZydbj5nRkTC/1VT87SFf+S+k66J8ycfIs2nkwlIvHWo+TbD36fBcTNq69BtAvluRRIH77zXg60zBK5KmmtKUbeayHVZngjZt/u3ezrRGuLu9TUCYtWMY0VVKyYUX36MykWY + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGFOUEXPF/20230518/eu-north-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=bfaefe50abefa68b0081af52687885a7391006f2c8b0d80b6c20beb7da808d56 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 403 + message: Forbidden + headers: + X-Amzn-Requestid: + - bdf82d4c-a300-4323-aa26-08cba28de47e + Content-Type: + - text/xml + Content-Length: + - '300' + Date: + - Thu, 18 May 2023 16:08:41 GMT + body: + encoding: UTF-8 + string: | + + + Sender + SignatureDoesNotMatch + Credential should be scoped to a valid region. + + bdf82d4c-a300-4323-aa26-08cba28de47e + + recorded_at: Thu, 18 May 2023 16:08:41 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-global-headers.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-global-headers.yml new file mode 100644 index 0000000000..ba3ce74486 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-global-headers.yml @@ -0,0 +1,52 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T152525Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/us-east-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=81b929060b45f05470c9f542a9e46cdce51d37c1d22a58d1942b7fa175079af5 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + X-Amzn-Requestid: + - c626dec1-0bb0-42c9-82b5-cc957aeca0a5 + Content-Type: + - text/xml + Content-Length: + - '456' + Date: + - Thu, 18 May 2023 15:28:32 GMT + body: + encoding: UTF-8 + string: | + + + arn:aws:sts::188945769008:assumed-role/conjur-role/i-08241b0e31fe23d20 + AROASX7QLUIYK4AQBODTV:i-08241b0e31fe23d20 + 188945769008 + + + c626dec1-0bb0-42c9-82b5-cc957aeca0a5 + + + recorded_at: Thu, 18 May 2023 15:28:33 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-regional-headers.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-regional-headers.yml new file mode 100644 index 0000000000..bf4a4681ae --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/valid-regional-headers.yml @@ -0,0 +1,52 @@ +--- +http_interactions: +- request: + method: get + uri: https://sts.eu-central-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 + body: + encoding: US-ASCII + string: '' + headers: + X-Amz-Date: + - 20230518T152442Z + X-Amz-Security-Token: + - IQoJb3JpZ2luX2VjEDcaDGV1LWNlbnRyYWwtMSJGMEQCIB7Inb5Q2L+Tu0nDM6KpYkqjXetnd6Eizw9gt3c27+okAiBJHE59aL6HuIszrEmk7/SaclqSmEZ5xUmEJ10Hla8PYyq8BQhgEAMaDDE4ODk0NTc2OTAwOCIMg1WLlzrcLY1FHaQKKpkFcEmdxNL2sGdxHOhoLv5hf0pQsOhWciwMgGhGpSUM7gXSG6Z8Rqv7q1rqgl04BjxLZshOOJYdIfUjUNccgiWBofjRYNH5SGeuLuu7XfrtmGmToPSejG5vY76PFXyef4bRNpgkB2aTRjRIg/fInQF0y2oILUSbX4nUcvcJJpss7VnpGRgGqGE+HtatAnfAn0cVoPHs/I2oZslP9y2IVVAEbCxKhYUcHniCJzrmTrppczyd8bwC36wdhcN88YtUES3Z0sS9Ho3JcLbxeAnoqkuPng1VYLAt5uELOqqYWSsdqVFwc+PJ5JoBAJSab1dyPp/YhTg+Lp8pYm/cgSR4lygqgeElL+30tI77GFuMdxdnWymk1mvXtcr0Q/eOMpAETohivAEW+m4CglAEF3VTdLQXODKCvxsiUmsN5AanX7eKGeHPfy/mcM/srWWkVNeRk//DLFNSgfiaeBQeUpzRDEgVpweA4tf5xjW8oUxp9hK9Q872dxgye07bFLNXbyqK9NPAGIcD4/7Tw73kPxYSvZ+7wajgkGdcuIz91GR973QG2k5e82PwiiROOm8qEJo7QzPX6hF5s//qSnKr0vGo4tBrewKvQVjhafdf+B0b44jgw7kIsUkAYz/1HY2PPQVvVn5DayO7VxCTTd+VrQScr22ExOucIKEw30j5hCkhRnUMS6MAjsYwclSbPuUeZ8rVvFQSEoC37SQZP13OVphFNUUFVhZJU5kYd9BvaFhPO0F54XJq1Gu/biMJFumHj2lz5TadSXxyJwSJkfqE53B9b6Sc1RB7O4AckozmH/pm46fJpD5sq7RLQg9YLA//fi+EoBwqbiskCz7WRsCh/Q2l/dmA9kAPPVatqkagVdcJKAJNl8W4Y9nm9MBhdFIw4PeYowY6sgF2td8Xkg0E4ClmQ3CoGWO+TTWmiWwN0BAcKD5prq3V9qmn3SXnzLUO02k0gC4RsdGUCSiByzNHL3mG+G7l8MEZ8TmZQ+ZCgtlnvLYsdECiT+7tcrwN8Zpiu0BKcAWSV8Mg5/D0HYfDTFAv7jgqXuL+uruLJw4xzZCoWc5Ru1Mhprl4NF8T9Am2RyEEEO9rjveQCWpzaZmyvx/MS4isoqhC2KGeJEyeulk2XE0mXO6TZz9c + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Authorization: + - AWS4-HMAC-SHA256 Credential=ASIASX7QLUIYGDI4QX56/20230518/eu-central-1/sts/aws4_request, + SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=8e0bebec9a3ce860b4595a4b27710da558a157a711e2dcbfe3a86881af99c459 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + X-Amzn-Requestid: + - c025e1ba-c36b-4078-9407-fdd02eaee5aa + Content-Type: + - text/xml + Content-Length: + - '456' + Date: + - Thu, 18 May 2023 15:28:33 GMT + body: + encoding: UTF-8 + string: | + + + arn:aws:sts::188945769008:assumed-role/conjur-role/i-08241b0e31fe23d20 + AROASX7QLUIYK4AQBODTV:i-08241b0e31fe23d20 + 188945769008 + + + c025e1ba-c36b-4078-9407-fdd02eaee5aa + + + recorded_at: Thu, 18 May 2023 15:28:33 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/verify-expired-headers.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-iam/verify-expired-headers.yml deleted file mode 100644 index c029eb78d5..0000000000 --- a/spec/fixtures/vcr_cassettes/authenticators/authn-iam/verify-expired-headers.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- -http_interactions: -- request: - method: get - uri: https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15 - body: - encoding: US-ASCII - string: '' - headers: - Accept: - - "*/*" - User-Agent: - - rest-client/2.1.0 (linux x86_64) ruby/3.0.5p211 - X-Amz-Date: - - 20180620T025910Z - X-Amz-Security-Token: - - FQoDYXdzEPv//////////wEaDHwvkDqh5pHmZNe5hSK3AzevmnHjzweG6m1in/CQ8NB7PCY0nTtWsCXLU5FsHmOoXs6KgVOu8ucghebak4b/iaDCpSprH3GPjLcNatywkUEQqX8rQKy2DoKMy7ZMHNT1ivhEn - vE3HR0GPkkGGWYhLTTrQDdI5fBcb3yJ /TyrcmUuBTKXwQJmvcnDe505SPpuSZm7tdrDX5SpItMngqGcrRhCjuprpk5nPVwSQq6usp7hJYPmu/6u9eVP3rQ - TFPldhRvRxu5rcssURdrIwbjMugZQff/8XERxyxPrTkJQekcqMvvV6gexDZcBOS1JtIsKfJEXUmK3kwV4liQsUevxyanWMc4jT0tiBkDj2 - nvXUFt6dejppdTTRdEtBXg5xZUrGDCQDUU9eBgydoTLGav9rWiM7bWtpP4A1m0E9LoX47FScSDkqk0Hy6Dr9jzhb4HOodlgaldTs8BNlgN9xXgACdacdPqnhaYLCgAWsaUZPKuZmdyH96F59rcrVscf456ivXTrXpt6pL1ZQyRCc04hkovErvv1L2CwEaGAc - k0bvbq0pbzTftTh7 9xY3pFxbL AALoR0t2/CfhyomvoG72Cl/nvAo7 m2QU - X-Amz-Content-Sha256: - - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - Authorization: - - AWS4-HMAC-SHA256 Credential=ASIAJJTVXJS5KDKXKNPQ/20180620/us-east-1/sts/aws4_request, - SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=230fa38a232969747b77e82f6c845f63941ebde89eb2cc20ed1c6f2dbabc92b6 - Accept-Encoding: - - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - response: - status: - code: 403 - message: Forbidden - headers: - X-Amzn-Requestid: - - 8c409194-abfc-4e7a-914d-e6c63c4b6ebf - Content-Type: - - text/xml - Content-Length: - - '354' - Date: - - Tue, 05 Jul 2022 14:09:51 GMT - body: - encoding: UTF-8 - string: | - - - Sender - SignatureDoesNotMatch - Signature expired: 20180620T025910Z is now earlier than 20220705T135452Z (20220705T140952Z - 15 min.) - - 8c409194-abfc-4e7a-914d-e6c63c4b6ebf - - recorded_at: Tue, 05 Jul 2022 14:09:51 GMT -recorded_with: VCR 6.1.0 From 85ec22a4e96bee6b5848d143824ae240b906760a Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Mon, 15 May 2023 15:35:30 -0600 Subject: [PATCH 27/42] Pulls conjur-rack gem directly into Conjur Conjur is currently the only project which uses the conjur-rack gem. This PR brings it into Conjur to simplify the authorization process. --- Gemfile | 2 +- Gemfile.lock | 14 +- Jenkinsfile | 9 + gems/conjur-rack/CHANGELOG.md | 54 +++++ gems/conjur-rack/CONTRIBUTING.md | 16 ++ gems/conjur-rack/Gemfile | 12 + gems/conjur-rack/LICENSE.txt | 22 ++ gems/conjur-rack/README.md | 27 +++ gems/conjur-rack/Rakefile | 14 ++ gems/conjur-rack/conjur-rack.gemspec | 32 +++ gems/conjur-rack/lib/conjur/rack.rb | 26 +++ .../lib/conjur/rack/authenticator.rb | 196 ++++++++++++++++ .../lib/conjur/rack/path_prefix.rb | 31 +++ gems/conjur-rack/lib/conjur/rack/user.rb | 141 +++++++++++ gems/conjur-rack/lib/conjur/rack/version.rb | 5 + .../spec/rack/authenticator_spec.rb | 181 ++++++++++++++ .../conjur-rack/spec/rack/path_prefix_spec.rb | 40 ++++ gems/conjur-rack/spec/rack/user_spec.rb | 221 ++++++++++++++++++ gems/conjur-rack/spec/rack_spec.rb | 49 ++++ gems/conjur-rack/spec/spec_helper.rb | 47 ++++ gems/conjur-rack/test.sh | 12 + 21 files changed, 1145 insertions(+), 6 deletions(-) create mode 100644 gems/conjur-rack/CHANGELOG.md create mode 100644 gems/conjur-rack/CONTRIBUTING.md create mode 100644 gems/conjur-rack/Gemfile create mode 100644 gems/conjur-rack/LICENSE.txt create mode 100644 gems/conjur-rack/README.md create mode 100644 gems/conjur-rack/Rakefile create mode 100644 gems/conjur-rack/conjur-rack.gemspec create mode 100644 gems/conjur-rack/lib/conjur/rack.rb create mode 100644 gems/conjur-rack/lib/conjur/rack/authenticator.rb create mode 100644 gems/conjur-rack/lib/conjur/rack/path_prefix.rb create mode 100644 gems/conjur-rack/lib/conjur/rack/user.rb create mode 100644 gems/conjur-rack/lib/conjur/rack/version.rb create mode 100644 gems/conjur-rack/spec/rack/authenticator_spec.rb create mode 100644 gems/conjur-rack/spec/rack/path_prefix_spec.rb create mode 100644 gems/conjur-rack/spec/rack/user_spec.rb create mode 100644 gems/conjur-rack/spec/rack_spec.rb create mode 100644 gems/conjur-rack/spec/spec_helper.rb create mode 100755 gems/conjur-rack/test.sh diff --git a/Gemfile b/Gemfile index 3ae65bcd57..7908f2c6ff 100644 --- a/Gemfile +++ b/Gemfile @@ -46,7 +46,7 @@ gem "loofah", ">= 2.2.3" # the branch doesn't immediately break this link gem 'conjur-api', '~> 5.pre' gem 'conjur-policy-parser', path: 'gems/policy-parser' -gem 'conjur-rack' +gem 'conjur-rack', path: 'gems/conjur-rack' gem 'conjur-rack-heartbeat' gem 'rack-rewrite' diff --git a/Gemfile.lock b/Gemfile.lock index 7082556903..5849b1b8d1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,11 @@ +PATH + remote: gems/conjur-rack + specs: + conjur-rack (5.0.0) + conjur-api (< 6) + rack (~> 2) + slosilo (~> 3.0) + PATH remote: gems/policy-parser specs: @@ -126,10 +134,6 @@ GEM conjur-cli (~> 6) docker-api (~> 2.0) gli - conjur-rack (5.0.0) - conjur-api (< 6) - rack (~> 2) - slosilo (~> 3.0) conjur-rack-heartbeat (2.2.0) rack contracts (0.17) @@ -519,7 +523,7 @@ DEPENDENCIES conjur-cli (~> 6.2) conjur-debify conjur-policy-parser! - conjur-rack + conjur-rack! conjur-rack-heartbeat csr cucumber (~> 7.1) diff --git a/Jenkinsfile b/Jenkinsfile index 38cd2f70ff..cef3cd441e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -41,6 +41,7 @@ These are defined in runConjurTests, and also include the one-offs authenticators_k8s rspec_audit policy_parser + conjur_rack azure_authenticator gcp_authenticator */ @@ -308,6 +309,7 @@ pipeline { container_logs/*/*, spec/reports/*.xml, spec/reports-audit/*.xml, + gems/conjur-rack/spec/reports/*.xml, cucumber/*/features/reports/**/*.xml ''' ) @@ -673,9 +675,11 @@ pipeline { junit(''' spec/reports/*.xml, spec/reports-audit/*.xml, + gems/conjur-rack/spec/reports/*.xml, cucumber/*/features/reports/**/*.xml, ee-test/spec/reports/*.xml, ee-test/spec/reports-audit/*.xml, + ee-test/gems/conjur-rack/spec/reports/*.xml, ee-test/cucumber/*/features/reports/**/*.xml ''' ) @@ -827,6 +831,11 @@ def runConjurTests(run_only_str) { "Policy Parser - ${env.STAGE_NAME}": { sh 'cd gems/policy-parser && ./test.sh' } + ], + "conjur_rack": [ + "Rack - ${env.STAGE_NAME}": { + sh 'cd gems/conjur-rack && ./test.sh' + } ] ] diff --git a/gems/conjur-rack/CHANGELOG.md b/gems/conjur-rack/CHANGELOG.md new file mode 100644 index 0000000000..2289ed3172 --- /dev/null +++ b/gems/conjur-rack/CHANGELOG.md @@ -0,0 +1,54 @@ +**This Gem has been moved into Conjur. All Conjur Rack Changelog entries should +appear in the main Changelog.** + +# unreleased version + +# v5.0.0 + +* Support Ruby 3. +* Bump `slosilo` to v3.0 with ruby 3. +* Remove pinned `bundler` version, use default system bundler. + +# v4.2.0 + +* Bump `slosilo` to v2.2 in order to be FIPS compliant + +# v4.0.0 + +* Bump `rack` to v2, `bundler` to v1.16 in gemspec +* Add Jenkinsfile to project +* Ignore headers such as Conjur-Privilege or Conjur-Audit if they're not +supported by the API (instead of erroring out). + +# v3.1.0 + +* Support for JWT Slosilo tokens. + +# v3.0.0.pre + +* Initial support for Conjur 5. + +# v2.3.0 + +* Add TRUSTED_PROXIES support + +# v2.2.0 + +* resolve 'own' token to CONJUR_ACCOUNT env var +* add #optional paths to Conjur::Rack authenticator + +# v2.1.0 + +* Add handling for `Conjur-Audit-Roles` and `Conjur-Audit-Resources` + +# v2.0.0 + +* Change `global_sudo?` to `global_elevate?` + +# v1.4.0 + +* Add `validated_global_privilege` helper function to get the global privilege, if any, which has been submitted with the request and verified by the Conjur server. + +# v1.3.0 + +* Add handling for `X-Forwarded-For` and `X-Conjur-Privilege` diff --git a/gems/conjur-rack/CONTRIBUTING.md b/gems/conjur-rack/CONTRIBUTING.md new file mode 100644 index 0000000000..7c0a67db14 --- /dev/null +++ b/gems/conjur-rack/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# Contributing + +For general contribution and community guidelines, please see the [community repo](https://github.com/cyberark/community). + +## Contributing Workflow + +1. [Fork the project](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) +2. [Clone your fork](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) +3. Make local changes to your fork by editing files +3. [Commit your changes](https://help.github.com/en/github/managing-files-in-a-repository/adding-a-file-to-a-repository-using-the-command-line) +4. [Push your local changes to the remote server](https://help.github.com/en/github/using-git/pushing-commits-to-a-remote-repository) +5. [Create new Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) + +From here your pull request will be reviewed and once you've responded to all +feedback it will be merged into the project. Congratulations, you're a +contributor! diff --git a/gems/conjur-rack/Gemfile b/gems/conjur-rack/Gemfile new file mode 100644 index 0000000000..ba44e6d927 --- /dev/null +++ b/gems/conjur-rack/Gemfile @@ -0,0 +1,12 @@ +source 'https://rubygems.org' + +# make sure github uses TLS +git_source(:github) { |name| "https://github.com/#{name}.git" } + +#ruby=ruby-3.0 +#ruby-gemset=conjur-rack + +# Specify your gem's dependencies in conjur-rack.gemspec +gemspec + +# gem 'conjur-api', github: 'cyberark/conjur-api-ruby', branch: 'master' diff --git a/gems/conjur-rack/LICENSE.txt b/gems/conjur-rack/LICENSE.txt new file mode 100644 index 0000000000..069db73dc1 --- /dev/null +++ b/gems/conjur-rack/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2020 CyberArk Software Ltd. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/gems/conjur-rack/README.md b/gems/conjur-rack/README.md new file mode 100644 index 0000000000..98b50e1a96 --- /dev/null +++ b/gems/conjur-rack/README.md @@ -0,0 +1,27 @@ +# Conjur::Rack + +TODO: Write a gem description + +## Installation + +Add this line to your application's Gemfile: + + gem 'conjur-rack' + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install conjur-rack + +## Usage + +TODO: Write usage instructions here + +## Contributing + +We welcome contributions of all kinds to this repository. For instructions on +how to get started and descriptions of our development workflows, please see our +[contributing guide](CONTRIBUTING.md). diff --git a/gems/conjur-rack/Rakefile b/gems/conjur-rack/Rakefile new file mode 100644 index 0000000000..d0c3eb3141 --- /dev/null +++ b/gems/conjur-rack/Rakefile @@ -0,0 +1,14 @@ +require "bundler/gem_tasks" +require 'rspec/core/rake_task' +require 'ci/reporter/rake/rspec' + +RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = "--format doc" + unless ENV["CONJUR_ENV"] == "ci" + t.rspec_opts << " --color" + else + Rake::Task["ci:setup:rspec"].invoke + end +end + +task :default => :spec diff --git a/gems/conjur-rack/conjur-rack.gemspec b/gems/conjur-rack/conjur-rack.gemspec new file mode 100644 index 0000000000..eea1fff30c --- /dev/null +++ b/gems/conjur-rack/conjur-rack.gemspec @@ -0,0 +1,32 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'conjur/rack/version' + +Gem::Specification.new do |spec| + spec.name = "conjur-rack" + spec.version = Conjur::Rack::VERSION + spec.authors = ["Kevin Gilpin"] + spec.email = ["kgilpin@conjur.net"] + spec.description = %q{Rack authenticator and basic User struct} + spec.summary = %q{Rack authenticator and basic User struct} + spec.homepage = "http://github.com/conjurinc/conjur-rack" + spec.license = "Private" + + spec.files = `git ls-files`.split($/) + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ["lib"] + + spec.add_dependency "slosilo", "~> 3.0" + spec.add_dependency "conjur-api", "< 6" + spec.add_dependency "rack", "~> 2" + + spec.add_development_dependency "rake" + spec.add_development_dependency "rspec" + spec.add_development_dependency "activesupport", "< 7" + spec.add_development_dependency 'ci_reporter_rspec' + spec.add_development_dependency 'pry-byebug' + spec.add_development_dependency 'rspec-its' + +end diff --git a/gems/conjur-rack/lib/conjur/rack.rb b/gems/conjur-rack/lib/conjur/rack.rb new file mode 100644 index 0000000000..1a9c353baf --- /dev/null +++ b/gems/conjur-rack/lib/conjur/rack.rb @@ -0,0 +1,26 @@ +require "conjur/rack/version" +require "conjur/rack/authenticator" +require "conjur/rack/path_prefix" +require 'ipaddr' +require 'set' + +module TrustedProxies + + def trusted_proxy?(ip) + trusted_proxies ? trusted_proxies.any? { |cidr| cidr.include?(ip) } : super + end + + def trusted_proxies + @trusted_proxies || ENV['TRUSTED_PROXIES'].try do |proxies| + cidrs = Set.new(proxies.split(',') + ['127.0.0.1']) + @trusted_proxies = cidrs.collect {|cidr| IPAddr.new(cidr) } + end + end + +end + +module Rack + class Request + prepend TrustedProxies + end +end diff --git a/gems/conjur-rack/lib/conjur/rack/authenticator.rb b/gems/conjur-rack/lib/conjur/rack/authenticator.rb new file mode 100644 index 0000000000..902240983b --- /dev/null +++ b/gems/conjur-rack/lib/conjur/rack/authenticator.rb @@ -0,0 +1,196 @@ +require "conjur/rack/user" + +module Conjur + module Rack + + class << self + def conjur_rack + Thread.current[:conjur_rack] ||= {} + end + + def identity? + !conjur_rack[:identity].nil? + end + + def user + User.new(identity[0], identity[1], + :privilege => privilege, + :remote_ip => remote_ip, + :audit_roles => audit_roles, + :audit_resources => audit_resources + ) + end + + def identity + conjur_rack[:identity] or raise "No Conjur identity for current request" + end + + # class attributes + [:privilege, :remote_ip, :audit_roles, :audit_resources].each do |a| + define_method(a) do + conjur_rack[a] + end + end + end + + + class Authenticator + class AuthorizationError < SecurityError + end + class SignatureError < SecurityError + end + class Forbidden < SecurityError + end + + attr_reader :app, :options + + # +options+: + # :except :: a list of request path patterns for which to skip authentication. + # :optional :: request path patterns for which authentication is optional. + def initialize app, options = {} + @app = app + @options = options + end + + # threadsafe accessors, values are established explicitly below + def env; Thread.current[:rack_env] ; end + + # instance attributes + [:token, :account, :privilege, :remote_ip, :audit_roles, :audit_resources].each do |a| + define_method(a) do + conjur_rack[a] + end + end + + def call rackenv + # never store request-specific variables as application attributes + Thread.current[:rack_env] = rackenv + if authenticate? + begin + identity = verify_authorization_and_get_identity # [token, account] + + if identity + conjur_rack[:token] = identity[0] + conjur_rack[:account] = identity[1] + conjur_rack[:identity] = identity + conjur_rack[:privilege] = http_privilege + conjur_rack[:remote_ip] = http_remote_ip + conjur_rack[:audit_roles] = http_audit_roles + conjur_rack[:audit_resources] = http_audit_resources + end + + rescue Forbidden + return error 403, $!.message + rescue SecurityError, RestClient::Exception + return error 401, $!.message + end + end + begin + @app.call rackenv + ensure + Thread.current[:rack_env] = nil + Thread.current[:conjur_rack] = {} + end + end + + protected + + def conjur_rack + Conjur::Rack.conjur_rack + end + + def validate_token_and_get_account token + failure = SignatureError.new("Unauthorized: Invalid token") + raise failure unless (signer = Slosilo.token_signer token) + if signer == 'own' + ENV['CONJUR_ACCOUNT'] or raise failure + else + raise failure unless signer =~ /\Aauthn:(.+)\z/ + $1 + end + end + + def error status, message + [status, { 'Content-Type' => 'text/plain', 'Content-Length' => message.length.to_s }, [message] ] + end + + def parsed_token + token = http_authorization.to_s[/^Token token="(.*)"/, 1] + token = token && JSON.parse(Base64.decode64(token)) + token = Slosilo::JWT token rescue token + rescue JSON::ParserError + raise AuthorizationError.new("Malformed authorization token") + end + + RECOGNIZED_CLAIMS = [ + 'iat', 'exp', # recognized by Slosilo + 'cidr', 'sub', + 'iss', 'aud', 'jti' # RFC 7519, not handled but recognized + ].freeze + + def verify_authorization_and_get_identity + if token = parsed_token + begin + account = validate_token_and_get_account token + if token.respond_to?(:claims) + claims = token.claims + raise AuthorizationError, "token contains unrecognized claims" unless \ + (claims.keys.map(&:to_s) - RECOGNIZED_CLAIMS).empty? + if (cidr = claims['cidr']) + raise Forbidden, "IP address rejected" unless \ + cidr.map(&IPAddr.method(:new)).any? { |c| c.include? http_remote_ip } + end + end + return [token, account] + end + else + path = http_path + if optional_paths.find{|p| p.match(path)}.nil? + raise AuthorizationError.new("Authorization missing") + else + nil + end + end + end + + def authenticate? + path = http_path + if options[:except] + options[:except].find{|p| p.match(path)}.nil? + else + true + end + end + + def optional_paths + options[:optional] || [] + end + + def http_authorization + env['HTTP_AUTHORIZATION'] + end + + def http_privilege + env['HTTP_X_CONJUR_PRIVILEGE'] + end + + def http_remote_ip + require 'rack/request' + ::Rack::Request.new(env).ip + end + + def http_audit_roles + env['HTTP_CONJUR_AUDIT_ROLES'] + end + + def http_audit_resources + env['HTTP_CONJUR_AUDIT_RESOURCES'] + end + + def http_path + [ env['SCRIPT_NAME'], env['PATH_INFO'] ].join + end + + end + end +end diff --git a/gems/conjur-rack/lib/conjur/rack/path_prefix.rb b/gems/conjur-rack/lib/conjur/rack/path_prefix.rb new file mode 100644 index 0000000000..511db284d3 --- /dev/null +++ b/gems/conjur-rack/lib/conjur/rack/path_prefix.rb @@ -0,0 +1,31 @@ +# https://raw.github.com/merb/merb/master/merb-core/lib/merb-core/rack/middleware/path_prefix.rb +module Conjur + module Rack + class PathPrefix + EMPTY_STRING = "" + SLASH = "/" + + # @api private + def initialize(app, path_prefix = nil) + @app = app + @path_prefix = /^#{Regexp.escape(path_prefix)}/ + end + + # @api plugin + def call(env) + strip_path_prefix(env) + @app.call(env) + end + + # @api private + def strip_path_prefix(env) + ['PATH_INFO', 'REQUEST_URI'].each do |path_key| + if env[path_key] =~ @path_prefix + env[path_key].sub!(@path_prefix, EMPTY_STRING) + env[path_key] = SLASH if env[path_key].empty? + end + end + end + end + end +end \ No newline at end of file diff --git a/gems/conjur-rack/lib/conjur/rack/user.rb b/gems/conjur-rack/lib/conjur/rack/user.rb new file mode 100644 index 0000000000..9680d2ee5a --- /dev/null +++ b/gems/conjur-rack/lib/conjur/rack/user.rb @@ -0,0 +1,141 @@ +require 'conjur/api' + +module Conjur + module Rack + # Token data can be a string (which is the user login), or a Hash. + # If it's a hash, it should contain the user login keyed by the string 'login'. + # The rest of the payload is available as +attributes+. + class User + attr_reader :token, :account, :privilege, :remote_ip, :audit_roles, :audit_resources + + def initialize(token, account, options = {}) + @token = token + @account = account + # Third argument used to be the name of privilege, be + # backwards compatible: + if options.respond_to?(:to_str) + @privilege = options + else + @privilege = options[:privilege] + @remote_ip = options[:remote_ip] + @audit_roles = options[:audit_roles] + @audit_resources = options[:audit_resources] + end + end + + # This file was accidently calling account conjur_account, + # I'm adding an alias in case that's going on anywhere else. + # -- Jon + alias :conjur_account :account + # alias :conjur_account= :account= + + # Returns the global privilege which was present on the request, if and only + # if the user actually has that privilege. + # + # Returns nil if no global privilege was present in the request headers, + # or if a global privilege was present in the request headers, but the user doesn't + # actually have that privilege according to the Conjur server. + def validated_global_privilege + unless @validated_global_privilege + @privilege = nil unless @privilege && + api.respond_to?(:global_privilege_permitted?) && + api.global_privilege_permitted?(@privilege) + @validated_global_privilege = true + end + @privilege + end + + # True if and only if the user has valid global 'reveal' privilege. + def global_reveal? + validated_global_privilege == "reveal" + end + + # True if and only if the user has valid global 'elevate' privilege. + def global_elevate? + validated_global_privilege == "elevate" + end + + def login + parse_token + + @login + end + + def attributes + parse_token + + @attributes || {} + end + + def roleid + tokens = login.split('/') + role_kind, roleid = if tokens.length == 1 + [ 'user', login ] + else + [ tokens[0], tokens[1..-1].join('/') ] + end + [ account, role_kind, roleid ].join(':') + end + + def role + api.role(roleid) + end + + def audit_resources + Conjur::API.decode_audit_ids(@audit_resources) if @audit_resources + end + + def audit_roles + Conjur::API.decode_audit_ids(@audit_roles) if @audit_roles + end + + def api(cls = Conjur::API) + args = [ token ] + args.push remote_ip if remote_ip + api = cls.new_from_token(*args) + + # These are features not present in some API versions. + # Test for them and only apply if it makes sense. Ignore otherwise. + %i(privilege audit_resources audit_roles).each do |feature| + meth = "with_#{feature}".intern + if api.respond_to?(meth) && (value = send(feature)) + api = api.send meth, value + end + end + + api + end + + protected + + def parse_token + return if @login + + @token = Slosilo::JWT token + load_jwt token + rescue ArgumentError + if data = token['data'] + return load_legacy data + else + raise "malformed token" + end + end + + def load_legacy data + if data.is_a?(String) + @login = token['data'] + elsif data.is_a?(Hash) + @attributes = token['data'].clone + @login = @attributes.delete('login') or raise "No 'login' field in token data" + else + raise "Expecting String or Hash token data, got #{data.class.name}" + end + end + + def load_jwt jwt + @attributes = jwt.claims.merge (jwt.header || {}) # just pass all the info + @login = jwt.claims['sub'] or raise "No 'sub' field in claims" + end + end + end +end diff --git a/gems/conjur-rack/lib/conjur/rack/version.rb b/gems/conjur-rack/lib/conjur/rack/version.rb new file mode 100644 index 0000000000..ad0a8d043c --- /dev/null +++ b/gems/conjur-rack/lib/conjur/rack/version.rb @@ -0,0 +1,5 @@ +module Conjur + module Rack + VERSION = "5.0.0" + end +end diff --git a/gems/conjur-rack/spec/rack/authenticator_spec.rb b/gems/conjur-rack/spec/rack/authenticator_spec.rb new file mode 100644 index 0000000000..6c0a1907bb --- /dev/null +++ b/gems/conjur-rack/spec/rack/authenticator_spec.rb @@ -0,0 +1,181 @@ +require 'spec_helper' + +require 'conjur/rack/authenticator' + +describe Conjur::Rack::Authenticator do + include_context "with authenticator" + + describe "#call" do + context "to an unprotected path" do + let(:except) { [ /^\/foo/ ] } + let(:env) { { 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo/bar' } } + before { + options[:except] = except + expect(app).to receive(:call).with(env).and_return app + } + context "without authorization" do + it "proceeds" do + expect(call).to eq(app) + expect(Conjur::Rack.identity?).to be(false) + end + end + context "with authorization" do + include_context "with authorization" + it "ignores the authorization" do + expect(call).to eq(app) + expect(Conjur::Rack.identity?).to be(false) + end + end + end + + context "to a protected path" do + let(:env) { { 'SCRIPT_NAME' => '/pathname' } } + context "without authorization" do + it "returns a 401 error" do + expect(call).to return_http 401, "Authorization missing" + end + end + context "with Conjur authorization" do + include_context "with authorization" + + context "with CIDR restriction" do + let(:claims) { { 'sub' => 'test-user', 'cidr' => %w(192.168.2.0/24 2001:db8::/32) } } + let(:token) { Slosilo::JWT.new(claims) } + before do + allow(subject).to receive_messages \ + parsed_token: token, + http_remote_ip: remote_ip + end + + %w(10.0.0.2 fdda:5cc1:23:4::1f).each do |addr| + context "with address #{addr} out of range" do + let(:remote_ip) { addr } + it "returns 403" do + expect(call).to return_http 403, "IP address rejected" + end + end + end + + %w(192.168.2.3 2001:db8::22).each do |addr| + context "with address #{addr} in range" do + let(:remote_ip) { addr } + it "passes the request" do + expect(call.login).to eq 'test-user' + end + end + end + end + + context "of a valid token" do + it 'launches app' do + expect(app).to receive(:call).with(env).and_return app + expect(call).to eq(app) + end + end + context "of an invalid token" do + it "returns a 401 error" do + allow(Slosilo).to receive(:token_signer).and_return(nil) + expect(call).to return_http 401, "Unauthorized: Invalid token" + end + end + context "of a token invalid for authn" do + it "returns a 401 error" do + allow(Slosilo).to receive(:token_signer).and_return('a-totally-different-key') + expect(call).to return_http 401, "Unauthorized: Invalid token" + end + end + context "of 'own' token" do + it "returns ENV['CONJUR_ACCOUNT']" do + expect(ENV).to receive(:[]).with("CONJUR_ACCOUNT").and_return("test-account") + expect(app).to receive(:call) do |*args| + expect(Conjur::Rack.identity?).to be(true) + expect(Conjur::Rack.user.account).to eq('test-account') + :done + end + allow(Slosilo).to receive(:token_signer).and_return('own') + expect(call).to eq(:done) + end + it "requires ENV['CONJUR_ACCOUNT']" do + expect(ENV).to receive(:[]).with("CONJUR_ACCOUNT").and_return(nil) + allow(Slosilo).to receive(:token_signer).and_return('own') + expect(call).to return_http 401, "Unauthorized: Invalid token" + end + end + end + + context "with junk in token" do + let(:env) { { 'HTTP_AUTHORIZATION' => 'Token token="open sesame"' } } + it "returns 401" do + expect(call).to return_http 401, "Malformed authorization token" + end + end + + context "with JSON junk in token" do + let(:env) { { 'HTTP_AUTHORIZATION' => 'Token token="eyJmb28iOiAiYmFyIn0="' } } + before do + allow(Slosilo).to receive(:token_signer).and_return(nil) + end + + it "returns 401" do + expect(call).to return_http 401, "Unauthorized: Invalid token" + end + end + end + context "to an optional path" do + let(:optional) { [ /^\/foo/ ] } + let(:env) { { 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo/bar' } } + before { + options[:optional] = optional + } + context "without authorization" do + it "proceeds" do + expect(app).to receive(:call) do |*args| + expect(Conjur::Rack.identity?).to be(false) + :done + end + expect(call).to eq(:done) + end + end + context "with authorization" do + include_context "with authorization" + it "processes the authorization" do + expect(app).to receive(:call) do |*args| + expect(Conjur::Rack.identity?).to be(true) + :done + end + expect(call).to eq(:done) + end + end + end + + RSpec::Matchers.define :return_http do |status, message| + match do |actual| + status, headers, body = actual + expect(status).to eq status + expect(headers).to eq "Content-Type" => "text/plain", "Content-Length" => message.length.to_s + expect(body.join).to eq message + end + end + end + + # protected internal methods + + describe '#verify_authorization_and_get_identity' do + it "accepts JWT tokens without CIDR restrictions" do + mock_jwt sub: 'user' + expect { subject.send :verify_authorization_and_get_identity }.to_not raise_error + end + + it "rejects JWT tokens with unrecognized claims" do + mock_jwt extra: 'field' + expect { subject.send :verify_authorization_and_get_identity }.to raise_error \ + Conjur::Rack::Authenticator::AuthorizationError + end + + def mock_jwt claims + token = Slosilo::JWT.new(claims).add_signature(alg: 'none') {} + allow(subject).to receive(:parsed_token) { token } + allow(Slosilo).to receive(:token_signer).with(token).and_return 'authn:test' + end + end +end diff --git a/gems/conjur-rack/spec/rack/path_prefix_spec.rb b/gems/conjur-rack/spec/rack/path_prefix_spec.rb new file mode 100644 index 0000000000..41abf9d153 --- /dev/null +++ b/gems/conjur-rack/spec/rack/path_prefix_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +require 'conjur/rack/path_prefix' + +describe Conjur::Rack::PathPrefix do + let(:app) { double(:app) } + let(:prefix) { "/api" } + let(:path_prefix) { Conjur::Rack::PathPrefix.new(app, prefix) } + let(:call) { path_prefix.call env } + let(:env) { + { + 'PATH_INFO' => path + } + } + + context "#call" do + context "/api/hosts" do + let(:path) { "/api/hosts" } + it "matches" do + expect(app).to receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app + call + end + end + context "/api" do + let(:path) { "/api" } + it "doesn't erase the path completely" do + expect(app).to receive(:call).with({ 'PATH_INFO' => '/' }).and_return app + call + end + end + context "with non-matching prefix" do + let(:path) { "/hosts" } + it "doesn't match" do + expect(app).to receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app + call + end + end + end + +end \ No newline at end of file diff --git a/gems/conjur-rack/spec/rack/user_spec.rb b/gems/conjur-rack/spec/rack/user_spec.rb new file mode 100644 index 0000000000..e1f138a429 --- /dev/null +++ b/gems/conjur-rack/spec/rack/user_spec.rb @@ -0,0 +1,221 @@ +require 'spec_helper' +require 'conjur/rack/user' + +describe Conjur::Rack::User do + let(:login){ 'admin' } + let(:token){ {'data' => login} } + let(:account){ 'acct' } + let(:privilege) { nil } + let(:remote_ip) { nil } + let(:audit_roles) { nil } + let(:audit_resources) { nil } + + subject(:user) { + described_class.new(token, account, + :privilege => privilege, + :remote_ip => remote_ip, + :audit_roles => audit_roles, + :audit_resources => audit_resources + ) + } + + it 'provides field accessors' do + expect(user.token).to eq token + expect(user.account).to eq account + expect(user.conjur_account).to eq account + expect(user.login).to eq login + end + + describe '#roleid' do + let(:login){ tokens.join('/') } + + context "when login contains one token" do + let(:tokens) { %w(foobar) } + + it "is expanded to account:user:token" do + expect(subject.roleid).to eq "#{account}:user:foobar" + end + end + + context "when login contains two tokens" do + let(:tokens) { %w(foo bar) } + + it "is expanded to account:first:second" do + expect(subject.roleid).to eq "#{account}:foo:bar" + end + end + + context "when login contains three tokens" do + let(:tokens) { %w(foo bar baz) } + + it "is expanded to account:first:second/third" do + expect(subject.roleid).to eq "#{account}:foo:bar/baz" + end + end + end + + describe '#role' do + let(:roleid){ 'the role id' } + let(:api){ double('conjur api') } + before do + allow(subject).to receive(:roleid).and_return roleid + allow(subject).to receive(:api).and_return api + end + + it 'passes roleid to api.role' do + expect(api).to receive(:role).with(roleid).and_return 'the role' + expect(subject.role).to eq('the role') + end + end + + describe "#global_reveal?" do + let(:api){ double "conjur-api" } + before { allow(subject).to receive(:api).and_return(api) } + + context "with global privilege" do + let(:privilege) { "reveal" } + + context "when not supported" do + before { expect(api).not_to respond_to :global_privilege_permitted? } + it "simply returns false" do + expect(subject.global_reveal?).to be false + end + end + + context "when supported" do + before do + allow(api).to receive(:global_privilege_permitted?).with('reveal') { true } + end + it "checks the API function global_privilege_permitted?" do + expect(subject.global_reveal?).to be true + # The result is cached + expect(api).not_to receive :global_privilege_permitted? + subject.global_reveal? + end + end + end + + context "without a global privilege" do + it "simply returns false" do + expect(subject.global_reveal?).to be false + end + end + end + + describe '#api' do + context "when given a class" do + let(:cls){ double('API class') } + it "calls cls.new_from_token with its token" do + expect(cls).to receive(:new_from_token).with(token).and_return 'the api' + expect(subject.api(cls)).to eq('the api') + end + end + + context 'when not given args' do + let(:api) { double :api } + before do + allow(Conjur::API).to receive(:new_from_token).with(token).and_return(api) + end + + it "builds the api from token" do + expect(subject.api).to eq api + end + + context "with remote_ip" do + let(:remote_ip) { "the-ip" } + it "passes the IP to the API constructor" do + expect(Conjur::API).to receive(:new_from_token).with(token, 'the-ip').and_return(api) + expect(subject.api).to eq api + end + end + + context "with privilege" do + let(:privilege) { "elevate" } + it "applies the privilege on the API object" do + expect(api).to receive(:with_privilege).with("elevate").and_return "privileged api" + expect(subject.api).to eq "privileged api" + end + end + + context "when audit supported" do + before do + # If we're testing on an API version that doesn't + # support audit this method will be missing, so stub. + unless Conjur::API.respond_to? :decode_audit_ids + # not exactly a faithful reimplementation, but good enough for here + allow(Conjur::API).to receive(:decode_audit_ids) {|x|[x]} + end + end + + context "with audit resource" do + let (:audit_resources) { 'food:bacon' } + it "applies the audit resource on the API object" do + expect(api).to receive(:with_audit_resources).with(['food:bacon']).and_return('the api') + expect(subject.api).to eq 'the api' + end + end + + context "with audit roles" do + let (:audit_roles) { 'user:cook' } + it "applies the audit role on the API object" do + expect(api).to receive(:with_audit_roles).with(['user:cook']).and_return('the api') + expect(subject.api).to eq 'the api' + end + end + end + + context "when audit not supported" do + before do + expect(api).not_to respond_to :with_audit_resources + expect(api).not_to respond_to :with_audit_roles + end + let (:audit_resources) { 'food:bacon' } + let (:audit_roles) { 'user:cook' } + it "ignores audit roles and resources" do + expect(subject.api).to eq api + end + end + end + end + + context "with invalid type payload" do + let(:token){ { "data" => :alice } } + it "raises an error on trying to access the content" do + expect{ subject.login }.to raise_error("Expecting String or Hash token data, got Symbol") + end + end + + context "with hash payload" do + let(:token){ { "data" => { "login" => "alice", "capabilities" => { "fry" => "bacon" } } } } + + it "processes the login and attributes" do + original_token = token.deep_dup + + expect(subject.login).to eq('alice') + expect(subject.attributes).to eq({"capabilities" => { "fry" => "bacon" }}) + + expect(token).to eq original_token + end + end + + context "with JWT token" do + let(:token) { {"protected"=>"eyJhbGciOiJ0ZXN0IiwidHlwIjoiSldUIn0=", + "payload"=>"eyJzdWIiOiJhbGljZSIsImlhdCI6MTUwNDU1NDI2NX0=", + "signature"=>"dGVzdHNpZw=="} } + + it "processes the login and attributes" do + original_token = token.deep_dup + + expect(subject.login).to eq('alice') + + # TODO: should we only pass unrecognized attrs here? + expect(subject.attributes).to eq \ + 'alg' => 'test', + 'iat' => 1504554265, + 'sub' => 'alice', + 'typ' => 'JWT' + + expect(token).to eq original_token + end + end +end diff --git a/gems/conjur-rack/spec/rack_spec.rb b/gems/conjur-rack/spec/rack_spec.rb new file mode 100644 index 0000000000..02464cb21f --- /dev/null +++ b/gems/conjur-rack/spec/rack_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' +require 'conjur/rack' + +describe Conjur::Rack do + describe '.user' do + include_context "with authorization" + let(:stubuser) { double :stubuser } + before do + allow(Conjur::Rack::User).to receive(:new) + .with(token, 'someacc', {:privilege => privilege, :remote_ip => remote_ip, :audit_roles => audit_roles, :audit_resources => audit_resources}) + .and_return(stubuser) + end + + context 'when called in app context' do + shared_examples_for :returns_user do + it "returns user built from token" do + expect(call).to eq stubuser + end + end + + include_examples :returns_user + + context 'with X-Conjur-Privilege' do + let(:privilege) { "elevate" } + include_examples :returns_user + end + + context 'with X-Forwarded-For' do + let(:remote_ip) { "66.0.0.1" } + include_examples :returns_user + end + + context 'with Conjur-Audit-Roles' do + let (:audit_roles) { 'user%3Acook' } + include_examples :returns_user + end + + context 'with Conjur-Audit-Resources' do + let (:audit_resources) { 'food%3Abacon' } + include_examples :returns_user + end + + end + + it "raises error if called out of app context" do + expect { Conjur::Rack.user }.to raise_error('No Conjur identity for current request') + end + end +end diff --git a/gems/conjur-rack/spec/spec_helper.rb b/gems/conjur-rack/spec/spec_helper.rb new file mode 100644 index 0000000000..e35d2880d5 --- /dev/null +++ b/gems/conjur-rack/spec/spec_helper.rb @@ -0,0 +1,47 @@ +require 'rubygems' +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") +$:.unshift File.join(File.dirname(__FILE__), "lib") + +# Allows loading of an environment config based on the environment +require 'rspec' +require 'rspec/its' +require 'securerandom' +require 'slosilo' + +RSpec.configure do |config| +end + +RSpec.shared_context "with authenticator" do + let(:options) { {} } + let(:app) { double(:app) } + subject(:authenticator) { Conjur::Rack::Authenticator.new(app, options) } + let(:call) { authenticator.call env } +end + +RSpec.shared_context "with authorization" do + include_context "with authenticator" + let(:token_signer) { "authn:someacc" } + let(:audit_resources) { nil } + let(:privilege) { nil } + let(:remote_ip) { nil } + let(:audit_roles) { nil } + + before do + allow(app).to receive(:call) { Conjur::Rack.user } + allow(Slosilo).to receive(:token_signer).and_return(token_signer) + end + + let(:env) do + { + 'HTTP_AUTHORIZATION' => "Token token=\"#{basic_64}\"" + }.tap do |e| + e['HTTP_X_CONJUR_PRIVILEGE'] = privilege if privilege + e['HTTP_X_FORWARDED_FOR'] = remote_ip if remote_ip + e['HTTP_CONJUR_AUDIT_ROLES'] = audit_roles if audit_roles + e['HTTP_CONJUR_AUDIT_RESOURCES'] = audit_resources if audit_resources + end + end + + let(:basic_64) { Base64.strict_encode64(token.to_json) } + let(:token) { { "data" => "foobar" } } +end diff --git a/gems/conjur-rack/test.sh b/gems/conjur-rack/test.sh new file mode 100755 index 0000000000..ad12ad8cf4 --- /dev/null +++ b/gems/conjur-rack/test.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e + +TEST_IMAGE='ruby:3.0' + +rm -f Gemfile.lock + +docker run --rm \ + -v "$PWD:/usr/src/app" \ + -w /usr/src/app \ + -e CONJUR_ENV=ci \ + $TEST_IMAGE \ + bash -c "gem update --system && bundle update && bundle exec rake spec" From 55692cce5be84cbf8390759a861d94ec296c19fb Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Tue, 23 May 2023 15:24:51 -0600 Subject: [PATCH 28/42] Removes a Git call from gemspec This commit: - Replaces a call to `git` with the equivalent Ruby call. This prevents a Git permission error. - Addresses all Rubocop warnings. --- gems/conjur-rack/conjur-rack.gemspec | 42 +++++++++++++--------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/gems/conjur-rack/conjur-rack.gemspec b/gems/conjur-rack/conjur-rack.gemspec index eea1fff30c..a4627220a4 100644 --- a/gems/conjur-rack/conjur-rack.gemspec +++ b/gems/conjur-rack/conjur-rack.gemspec @@ -1,32 +1,28 @@ -# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'conjur/rack/version' Gem::Specification.new do |spec| - spec.name = "conjur-rack" - spec.version = Conjur::Rack::VERSION - spec.authors = ["Kevin Gilpin"] - spec.email = ["kgilpin@conjur.net"] - spec.description = %q{Rack authenticator and basic User struct} - spec.summary = %q{Rack authenticator and basic User struct} - spec.homepage = "http://github.com/conjurinc/conjur-rack" - spec.license = "Private" + spec.name = 'conjur-rack' + spec.version = Conjur::Rack::VERSION + spec.authors = ['Cyberark R&D'] + spec.summary = 'Rack authenticator and basic User struct' + spec.homepage = 'http://github.com/conjurinc/conjur-rack' - spec.files = `git ls-files`.split($/) - spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) - spec.require_paths = ["lib"] + spec.files = Dir.glob("lib/**/*") + %w[README.md] + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.5' - spec.add_dependency "slosilo", "~> 3.0" - spec.add_dependency "conjur-api", "< 6" - spec.add_dependency "rack", "~> 2" - - spec.add_development_dependency "rake" - spec.add_development_dependency "rspec" - spec.add_development_dependency "activesupport", "< 7" - spec.add_development_dependency 'ci_reporter_rspec' - spec.add_development_dependency 'pry-byebug' - spec.add_development_dependency 'rspec-its' + spec.add_dependency('conjur-api', '< 6') + spec.add_dependency('rack', '~> 2') + spec.add_dependency('slosilo', '~> 3.0') + spec.add_development_dependency('activesupport', '< 7') + spec.add_development_dependency('ci_reporter_rspec') + spec.add_development_dependency('pry-byebug') + spec.add_development_dependency('rake') + spec.add_development_dependency('rspec') + spec.add_development_dependency('rspec-its') end From 2ec58b686020295ede296a71ce5add99f04f4c2e Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Thu, 25 May 2023 10:30:37 -0400 Subject: [PATCH 29/42] Fix AuthnJWT test case ONYX-10960 Failure caused by regex update in cyberark/conjur#2792 --- cucumber/authenticators_jwt/features/authn_status_jwt.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber/authenticators_jwt/features/authn_status_jwt.feature b/cucumber/authenticators_jwt/features/authn_status_jwt.feature index b8dfbef350..3953407b3f 100644 --- a/cucumber/authenticators_jwt/features/authn_status_jwt.feature +++ b/cucumber/authenticators_jwt/features/authn_status_jwt.feature @@ -1108,7 +1108,7 @@ Feature: JWT Authenticator - Status Check And I save my place in the log file When I GET "/authn-jwt/raw/cucumber/status" Then the HTTP response status code is 500 - And the authenticator status check fails with error "does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|-|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|-|0-9|.]*)*$)" + And the authenticator status check fails with error "does not match regular expression: '(?-mix:^[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*(\/[a-zA-Z|$|_][a-zA-Z|$|_|\-|0-9|.]*)*$)" @negative @acceptance Scenario Outline: ONYX-10958: claim-aliases configured with invalid value, 500 Error From 8499035ab20d105c2a2bebb0167d4b8cd5614787 Mon Sep 17 00:00:00 2001 From: John ODonnell Date: Thu, 13 Apr 2023 11:00:10 -0400 Subject: [PATCH 30/42] AuthnOIDC V2: mask Identity error messages Includes RSpec unit tests for these cases, along with VCR cassettes to playback authentic Identity responses. --- .../authentication/authn_oidc/v2/client.rb | 6 +- .../authn-oidc/v2/client_spec.rb | 315 ++++++++++-------- ...ck-expired_code-valid_oidc_credentials.yml | 34 ++ .../client_callback-invalid_code_verifier.yml | 33 ++ ...lback-used_code-valid_oidc_credentials.yml | 34 ++ .../authn-oidc/v2/identity/client_load.yml | 45 +++ ...covery_endpoint-valid_oidc_credentials.yml | 45 +++ ...ck-expired_code-valid_oidc_credentials.yml | 2 +- .../client_callback-invalid_code_verifier.yml | 2 +- ...lback-used_code-valid_oidc_credentials.yml | 2 +- ...client_callback-valid_oidc_credentials.yml | 2 +- .../v2/{ => okta-2}/client_initialization.yml | 0 .../v2/{ => okta-2}/client_load.yml | 0 ...covery_endpoint-valid_oidc_credentials.yml | 0 14 files changed, 378 insertions(+), 142 deletions(-) create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-expired_code-valid_oidc_credentials.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-invalid_code_verifier.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-used_code-valid_oidc_credentials.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_load.yml create mode 100644 spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/discovery_endpoint-valid_oidc_credentials.yml rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_callback-expired_code-valid_oidc_credentials.yml (93%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_callback-invalid_code_verifier.yml (92%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_callback-used_code-valid_oidc_credentials.yml (96%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_callback-valid_oidc_credentials.yml (98%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_initialization.yml (100%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/client_load.yml (100%) rename spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/{ => okta-2}/discovery_endpoint-valid_oidc_credentials.yml (100%) diff --git a/app/domain/authentication/authn_oidc/v2/client.rb b/app/domain/authentication/authn_oidc/v2/client.rb index 60756403de..80a82c00c2 100644 --- a/app/domain/authentication/authn_oidc/v2/client.rb +++ b/app/domain/authentication/authn_oidc/v2/client.rb @@ -45,10 +45,12 @@ def callback(code:, nonce:, code_verifier: nil) rescue Rack::OAuth2::Client::Error => e # Only handle the expected errors related to access token retrieval. case e.message - when /PKCE verification failed/ + when /PKCE verification failed/, # Okta's PKCE failure msg + /challenge mismatch/ # Identity's PKCE failure msg raise Errors::Authentication::AuthnOidc::TokenRetrievalFailed, 'PKCE verification failed' - when /The authorization code is invalid or has expired/ + when /The authorization code is invalid or has expired/, # Okta's reused code msg + /supplied code does not match known request/ # Identity's reused code msg raise Errors::Authentication::AuthnOidc::TokenRetrievalFailed, 'Authorization code is invalid or has expired' when /Code not valid/ diff --git a/spec/app/domain/authentication/authn-oidc/v2/client_spec.rb b/spec/app/domain/authentication/authn-oidc/v2/client_spec.rb index 9c2d983c4f..9fdf0190d6 100644 --- a/spec/app/domain/authentication/authn-oidc/v2/client_spec.rb +++ b/spec/app/domain/authentication/authn-oidc/v2/client_spec.rb @@ -3,22 +3,18 @@ require 'spec_helper' RSpec.describe(Authentication::AuthnOidc::V2::Client) do - let(:authenticator) do - Authentication::AuthnOidc::V2::DataObjects::Authenticator.new( - provider_uri: 'https://dev-92899796.okta.com/oauth2/default', - redirect_uri: 'http://localhost:3000/authn-oidc/okta-2/cucumber/authenticate', - client_id: '0oa3w3xig6rHiu9yT5d7', - client_secret: 'e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj', - claim_mapping: 'foo', - account: 'bar', - service_id: 'baz' - ) - end - - let(:client) do - VCR.use_cassette("authenticators/authn-oidc/v2/client_load") do + def client(config) + VCR.use_cassette("authenticators/authn-oidc/v2/#{config[:service_id]}/client_load") do client = Authentication::AuthnOidc::V2::Client.new( - authenticator: authenticator + authenticator: Authentication::AuthnOidc::V2::DataObjects::Authenticator.new( + provider_uri: config[:provider_uri], + redirect_uri: "http://localhost:3000/authn-oidc/#{config[:service_id]}/cucumber/authenticate", + client_id: config[:client_id], + client_secret: config[:client_secret], + claim_mapping: "email", + account: "bar", + service_id: "baz" + ) ) # The call `oidc_client` queries the OIDC endpoint. As such, # we need to wrap this in a VCR call. Calling this before @@ -29,164 +25,211 @@ end end - describe '.callback', type: 'unit' do - context 'when credentials are valid' do - it 'returns a valid JWT token', vcr: 'authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials' do - # Because JWT tokens have an expiration timeframe, we need to hold - # time constant after caching the request. - travel_to(Time.parse("2022-09-30 17:02:17 +0000")) do - token = client.callback( - code: '-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw', - code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', - nonce: '7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d' - ) - expect(token).to be_a_kind_of(OpenIDConnect::ResponseObject::IdToken) - expect(token.raw_attributes['nonce']).to eq('7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d') - expect(token.raw_attributes['preferred_username']).to eq('test.user3@mycompany.com') - expect(token.aud).to eq('0oa3w3xig6rHiu9yT5d7') + shared_examples 'happy path' do |config| + describe '.callback', type: 'unit' do + context 'when credentials are valid' do + it 'returns a valid JWT token', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-valid_oidc_credentials" do + travel_to(Time.parse(config[:auth_time])) do + token = client(config).callback( + code: config[:code], + code_verifier: config[:code_verifier], + nonce: config[:nonce] + ) + expect(token).to be_a_kind_of(OpenIDConnect::ResponseObject::IdToken) + expect(token.raw_attributes['nonce']).to eq(config[:nonce]) + expect(token.raw_attributes['preferred_username']).to eq(config[:username]) + expect(token.aud).to eq(config[:client_id]) + end end end end + end - context 'when code verifier does not match' do - it 'raises an error', vcr: 'authenticators/authn-oidc/v2/client_callback-invalid_code_verifier' do - travel_to(Time.parse("2022-10-17 17:23:30 +0000")) do - expect do - client.callback( - code: 'GV48_SF4a19ghvBhVbbSG3Lr8BuFl8PhWVPZSbokV2o', - code_verifier: 'bad-code-verifier', - nonce: '3e6bd5235e4692b37ca1f04cb01b6e0cb177aa20dcef19e89f' + shared_examples 'token retrieval failures' do |config| + describe '.callback', type: 'unit' do + context 'when code verifier does not match' do + it 'raises an error', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-invalid_code_verifier" do + travel_to(Time.parse(config[:auth_time])) do + expect do + client(config).callback( + code: config[:code], + code_verifier: 'bad-code-verifier', + nonce: config[:nonce] + ) + end.to raise_error( + Errors::Authentication::AuthnOidc::TokenRetrievalFailed, + "CONJ00133E Access Token retrieval failure: 'PKCE verification failed'" ) - end.to raise_error( - Errors::Authentication::AuthnOidc::TokenRetrievalFailed, - "CONJ00133E Access Token retrieval failure: 'PKCE verification failed'" - ) + end end end - end - context 'when nonce does not match' do - it 'raises an error', vcr: 'authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials' do - travel_to(Time.parse("2022-09-30 17:02:17 +0000")) do + context 'when code has previously been used' do + it 'raise an exception', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-used_code-valid_oidc_credentials" do expect do - client.callback( - code: '-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw', - code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', - nonce: 'bad-nonce' + client(config).callback( + code: config[:code], + code_verifier: config[:code_verifier], + nonce: config[:nonce] ) end.to raise_error( - Errors::Authentication::AuthnOidc::TokenVerificationFailed, - "CONJ00128E JWT Token validation failed: 'Provided nonce does not match the nonce in the JWT'" + Errors::Authentication::AuthnOidc::TokenRetrievalFailed, + "CONJ00133E Access Token retrieval failure: 'Authorization code is invalid or has expired'" ) end end - end - - context 'when JWT has expired' do - it 'raises an error', vcr: 'authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials' do - travel_to(Time.parse("2022-10-01 17:02:17 +0000")) do + + context 'when code has expired', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-expired_code-valid_oidc_credentials" do + it 'raise an exception' do expect do - client.callback( - code: '-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw', - code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', - nonce: '7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d' + client(config).callback( + code: config[:code], + code_verifier: config[:code_verifier], + nonce: config[:nonce] ) end.to raise_error( - Errors::Authentication::AuthnOidc::TokenVerificationFailed, - "CONJ00128E JWT Token validation failed: 'JWT has expired'" + Errors::Authentication::AuthnOidc::TokenRetrievalFailed, + "CONJ00133E Access Token retrieval failure: 'Authorization code is invalid or has expired'" ) end end end + end - context 'when code has previously been used' do - it 'raise an exception', vcr: 'authenticators/authn-oidc/v2/client_callback-used_code-valid_oidc_credentials' do - expect do - client.callback( - code: '-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw', - code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', - nonce: '7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d' - ) - end.to raise_error( - Errors::Authentication::AuthnOidc::TokenRetrievalFailed, - "CONJ00133E Access Token retrieval failure: 'Authorization code is invalid or has expired'" - ) + shared_examples 'token validation failures' do |config| + describe '.callback', type: 'unit' do + context 'when nonce does not match' do + it 'raises an error', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-valid_oidc_credentials" do + travel_to(Time.parse(config[:auth_time])) do + expect do + client(config).callback( + code: config[:code], + code_verifier: config[:code_verifier], + nonce: 'bad-nonce' + ) + end.to raise_error( + Errors::Authentication::AuthnOidc::TokenVerificationFailed, + "CONJ00128E JWT Token validation failed: 'Provided nonce does not match the nonce in the JWT'" + ) + end + end end - end - context 'when code has expired', vcr: 'authenticators/authn-oidc/v2/client_callback-expired_code-valid_oidc_credentials' do - it 'raise an exception' do - expect do - client.callback( - code: 'SNSPeiQJ0-D6nUHTg-Ht9ZoDxIaaWBB80pnYuXY2VxU', - code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', - nonce: '7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d' - ) - end.to raise_error( - Errors::Authentication::AuthnOidc::TokenRetrievalFailed, - "CONJ00133E Access Token retrieval failure: 'Authorization code is invalid or has expired'" - ) + context 'when JWT has expired' do + it 'raises an error', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_callback-valid_oidc_credentials" do + travel_to(Time.parse(config[:auth_time]) + 86400) do + expect do + client(config).callback( + code: config[:code], + code_verifier: config[:code_verifier], + nonce: config[:nonce] + ) + end.to raise_error( + Errors::Authentication::AuthnOidc::TokenVerificationFailed, + "CONJ00128E JWT Token validation failed: 'JWT has expired'" + ) + end + end end end end - describe '.oidc_client', type: 'unit' do - context 'when credentials are valid' do - it 'returns a valid oidc client', vcr: 'authenticators/authn-oidc/v2/client_initialization' do - oidc_client = client.oidc_client - - expect(oidc_client).to be_a_kind_of(OpenIDConnect::Client) - expect(oidc_client.identifier).to eq('0oa3w3xig6rHiu9yT5d7') - expect(oidc_client.secret).to eq('e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj') - expect(oidc_client.redirect_uri).to eq('http://localhost:3000/authn-oidc/okta-2/cucumber/authenticate') - expect(oidc_client.scheme).to eq('https') - expect(oidc_client.host).to eq('dev-92899796.okta.com') - expect(oidc_client.port).to eq(443) - expect(oidc_client.authorization_endpoint).to eq('/oauth2/default/v1/authorize') - expect(oidc_client.token_endpoint).to eq('/oauth2/default/v1/token') - expect(oidc_client.userinfo_endpoint).to eq('/oauth2/default/v1/userinfo') + shared_examples 'client setup' do |config| + describe '.oidc_client', type: 'unit' do + context 'when credentials are valid' do + it 'returns a valid oidc client', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/client_initialization" do + oidc_client = client(config).oidc_client + + expect(oidc_client).to be_a_kind_of(OpenIDConnect::Client) + expect(oidc_client.identifier).to eq(config[:client_id]) + expect(oidc_client.secret).to eq(config[:client_secret]) + expect(oidc_client.redirect_uri).to eq("http://localhost:3000/authn-oidc/#{config[:service_id]}/cucumber/authenticate") + expect(oidc_client.scheme).to eq('https') + expect(oidc_client.host).to eq(config[:host]) + expect(oidc_client.port).to eq(443) + expect(oidc_client.authorization_endpoint).to eq(config[:expected_authz]) + expect(oidc_client.token_endpoint).to eq(config[:expected_token]) + expect(oidc_client.userinfo_endpoint).to eq(config[:expected_userinfo]) + end end end - end - describe '.discovery_information', type: 'unit', vcr: 'authenticators/authn-oidc/v2/discovery_endpoint-valid_oidc_credentials' do - context 'when credentials are valid' do - it 'endpoint returns valid data' do - discovery_information = client.discovery_information(invalidate: true) + describe '.discovery_information', type: 'unit', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/discovery_endpoint-valid_oidc_credentials" do + context 'when credentials are valid' do + it 'endpoint returns valid data' do + discovery_information = client(config).discovery_information(invalidate: true) - expect(discovery_information.authorization_endpoint).to eq( - 'https://dev-92899796.okta.com/oauth2/default/v1/authorize' - ) - expect(discovery_information.token_endpoint).to eq( - 'https://dev-92899796.okta.com/oauth2/default/v1/token' - ) - expect(discovery_information.userinfo_endpoint).to eq( - 'https://dev-92899796.okta.com/oauth2/default/v1/userinfo' - ) - expect(discovery_information.jwks_uri).to eq( - 'https://dev-92899796.okta.com/oauth2/default/v1/keys' - ) + expect(discovery_information.authorization_endpoint).to eq("https://#{config[:host]}#{config[:expected_authz]}") + expect(discovery_information.token_endpoint).to eq("https://#{config[:host]}#{config[:expected_token]}") + expect(discovery_information.userinfo_endpoint).to eq("https://#{config[:host]}#{config[:expected_userinfo]}") + expect(discovery_information.jwks_uri).to eq("https://#{config[:host]}#{config[:expected_keys]}") + end end - end - context 'when provider URI is invalid', vcr: 'authenticators/authn-oidc/v2/discovery_endpoint-invalid_oidc_provider' do - it 'returns an timeout error' do - client = Authentication::AuthnOidc::V2::Client.new( - authenticator: Authentication::AuthnOidc::V2::DataObjects::Authenticator.new( - provider_uri: 'https://foo.bar1234321.com', - redirect_uri: 'http://localhost:3000/authn-oidc/okta-2/cucumber/authenticate', - client_id: '0oa3w3xig6rHiu9yT5d7', - client_secret: 'e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj', - claim_mapping: 'foo', - account: 'bar', - service_id: 'baz' + context 'when provider URI is invalid', vcr: "authenticators/authn-oidc/v2/#{config[:service_id]}/discovery_endpoint-invalid_oidc_provider" do + it 'returns an timeout error' do + client = Authentication::AuthnOidc::V2::Client.new( + authenticator: Authentication::AuthnOidc::V2::DataObjects::Authenticator.new( + provider_uri: 'https://foo.bar1234321.com', + redirect_uri: "http://localhost:3000/authn-oidc/#{config[:service_id]}/cucumber/authenticate", + client_id: config[:client_id], + client_secret: config[:client_secret], + claim_mapping: config[:claim_mapping], + account: 'bar', + service_id: 'baz' + ) ) - ) - expect{client.discovery_information(invalidate: true)}.to raise_error( - Errors::Authentication::OAuth::ProviderDiscoveryFailed - ) + expect{client.discovery_information(invalidate: true)}.to raise_error( + Errors::Authentication::OAuth::ProviderDiscoveryFailed + ) + end end end end + + describe 'OIDC client targeting Okta' do + config = { + provider_uri: 'https://dev-92899796.okta.com/oauth2/default', + host: 'dev-92899796.okta.com', + client_id: '0oa3w3xig6rHiu9yT5d7', + client_secret: 'e349BMTTIpLO-rPuPqLLkLyH_pO-loUzhIVJCrHj', + service_id: 'okta-2', + expected_authz: '/oauth2/default/v1/authorize', + expected_token: '/oauth2/default/v1/token', + expected_userinfo: '/oauth2/default/v1/userinfo', + expected_keys: '/oauth2/default/v1/keys', + auth_time: '2022-09-30 17:02:17 +0000', + code: '-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw', + code_verifier: 'c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d', + nonce: '7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d', + username: 'test.user3@mycompany.com' + } + + include_examples 'client setup', config + include_examples 'happy path', config + include_examples 'token retrieval failures', config + include_examples 'token validation failures', config + end + + describe 'OIDC client targeting Identity' do + config = { + provider_uri: 'https://redacted-host/redacted_app/', + host: 'redacted-host', + client_id: 'redacted-id', + client_secret: 'redacted-secret', + service_id: 'identity', + expected_authz: '/OAuth2/Authorize/redacted_app', + expected_token: '/OAuth2/Token/redacted_app', + expected_userinfo: '/OAuth2/UserInfo/redacted_app', + expected_keys: '/OAuth2/Keys/redacted_app', + auth_time: '2023-4-10 18:00:00 +0000', + code: 'puPaKJOr_E25STHsM_-rOo3fgJBz2TKVNsi8GzBvwS41', + code_verifier: '9625bb8881c08de323bb17242d6b3552e50aec0e999e15c66a', + nonce: 'f1daadf8108eaf6ccf3295fd679acc5218f776d1aaaa3d270a' + } + + include_examples 'client setup', config + include_examples 'token retrieval failures', config + end end diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-expired_code-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-expired_code-valid_oidc_credentials.yml new file mode 100644 index 0000000000..e7bbc1eed8 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-expired_code-valid_oidc_credentials.yml @@ -0,0 +1,34 @@ +--- +http_interactions: +- request: + method: post + uri: https://redacted-host/OAuth2/Token/redacted_app + body: + encoding: UTF-8 + string: grant_type=authorization_code&code=puPaKJOr_E25STHsM_-rOo3fgJBz2TKVNsi8GzBvwS41&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fidentity%2Fcucumber%2Fauthenticate&scope=true&code_verifier=9625bb8881c08de323bb17242d6b3552e50aec0e999e15c66a + headers: + User-Agent: + - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.6 (2023-03-30)) + Accept: + - "*/*" + Date: + - Mon, 10 Apr 2023 23:45:36 GMT + Authorization: + - Basic cmVkYWN0ZWQtaWQ6cmVkYWN0ZWQtc2VjcmV0Cg== + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 400 + message: Bad Request + headers: + Date: + - Mon, 10 Apr 2023 23:45:36 GMT + Content-Length: + - '90' + body: + encoding: UTF-8 + string: '{"error":"invalid_grant","error_description":"supplied code does not + match known request"}' + recorded_at: Mon, 10 Apr 2023 23:45:36 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-invalid_code_verifier.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-invalid_code_verifier.yml new file mode 100644 index 0000000000..a1a032a787 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-invalid_code_verifier.yml @@ -0,0 +1,33 @@ +--- +http_interactions: +- request: + method: post + uri: https://redacted-host/OAuth2/Token/redacted_app + body: + encoding: UTF-8 + string: grant_type=authorization_code&code=puPaKJOr_E25STHsM_-rOo3fgJBz2TKVNsi8GzBvwS41&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fidentity%2Fcucumber%2Fauthenticate&scope=true&code_verifier=bad-code-verifier + headers: + User-Agent: + - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.6 (2023-03-30)) + Accept: + - "*/*" + Date: + - Mon, 17 Oct 2022 17:23:30 GMT + Authorization: + - Basic cmVkYWN0ZWQtaWQ6cmVkYWN0ZWQtc2VjcmV0Cg== + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 400 + message: Bad Request + headers: + Date: + - Mon, 10 Apr 2023 22:31:31 GMT + Content-Length: + - '66' + body: + encoding: UTF-8 + string: '{"error":"invalid_grant","error_description":"challenge mismatch"}' + recorded_at: Mon, 17 Oct 2022 17:23:30 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-used_code-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-used_code-valid_oidc_credentials.yml new file mode 100644 index 0000000000..588853ef54 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_callback-used_code-valid_oidc_credentials.yml @@ -0,0 +1,34 @@ +--- +http_interactions: +- request: + method: post + uri: https://redacted-host/OAuth2/Token/redacted_app + body: + encoding: UTF-8 + string: grant_type=authorization_code&code=puPaKJOr_E25STHsM_-rOo3fgJBz2TKVNsi8GzBvwS41&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fidentity%2Fcucumber%2Fauthenticate&scope=true&code_verifier=9625bb8881c08de323bb17242d6b3552e50aec0e999e15c66a + headers: + User-Agent: + - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.6 (2023-03-30)) + Accept: + - "*/*" + Date: + - Mon, 10 Apr 2023 21:48:37 GMT + Authorization: + - Basic cmVkYWN0ZWQtaWQ6cmVkYWN0ZWQtc2VjcmV0Cg== + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 400 + message: Bad Request + headers: + Date: + - Mon, 10 Apr 2023 21:48:37 GMT + Content-Length: + - '90' + body: + encoding: UTF-8 + string: '{"error":"invalid_grant","error_description":"supplied code does not + match known request"}' + recorded_at: Mon, 10 Apr 2023 21:48:37 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_load.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_load.yml new file mode 100644 index 0000000000..dce92df9da --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/client_load.yml @@ -0,0 +1,45 @@ +--- +http_interactions: +- request: + method: get + uri: https://redacted-host/redacted_app/.well-known/openid-configuration + body: + encoding: UTF-8 + string: '' + headers: + User-Agent: + - SWD (1.3.0) (2.8.3, ruby 3.0.6 (2023-03-30)) + Accept: + - "*/*" + Date: + - Mon, 10 Apr 2023 18:13:17 GMT + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 10 Apr 2023 18:13:17 GMT + Content-Length: + - '1347' + body: + encoding: UTF-8 + string: "{\r\n \"authorization_endpoint\": \"https://redacted-host/OAuth2/Authorize/redacted_app\",\r\n + \ \"code_challenge_methods_supported\": [\r\n \"plain\",\r\n \"S256\"\r\n + \ ],\r\n \"jwks_uri\": \"https://redacted-host/OAuth2/Keys/redacted_app\",\r\n + \ \"response_types_supported\": [\r\n \"code\",\r\n \"id_token\",\r\n + \ \"id_token token\",\r\n \"code id_token\",\r\n \"code token\",\r\n + \ \"code id_token token\"\r\n ],\r\n \"introspection_endpoint\": \"https://redacted-host/OAuth2/Introspect/redacted_app\",\r\n + \ \"id_token_signing_alg_values_supported\": [\r\n \"RS256\"\r\n ],\r\n + \ \"subject_types_supported\": [\r\n \"public\"\r\n ],\r\n \"issuer\": + \"https://redacted-host/redacted_app/\",\r\n \"userinfo_endpoint\": + \"https://redacted-host/OAuth2/UserInfo/redacted_app\",\r\n \"token_endpoint\": + \"https://redacted-host/OAuth2/Token/redacted_app\",\r\n \"scopes_supported\": + [\r\n \"openid\",\r\n \"profile\",\r\n \"email\",\r\n \"address\",\r\n + \ \"phone\"\r\n ],\r\n \"claims_supported\": [\r\n \"sub\",\r\n \"name\",\r\n + \ \"family_name\",\r\n \"given_name\",\r\n \"picture\",\r\n \"preferred_username\",\r\n + \ \"email\",\r\n \"email_verified\",\r\n \"phone_number\",\r\n \"phone_number_verified\",\r\n + \ \"address\",\r\n \"auth_time\",\r\n \"aud\",\r\n \"iss\",\r\n + \ \"exp\",\r\n \"iat\"\r\n ],\r\n \"end_session_endpoint\": \"https://redacted-host/OAuth2/EndSessionV2/redacted_app\"\r\n}" + recorded_at: Mon, 10 Apr 2023 18:13:17 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/discovery_endpoint-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/discovery_endpoint-valid_oidc_credentials.yml new file mode 100644 index 0000000000..bd889dabb1 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/identity/discovery_endpoint-valid_oidc_credentials.yml @@ -0,0 +1,45 @@ +--- +http_interactions: +- request: + method: get + uri: https://redacted-host/redacted_app/.well-known/openid-configuration + body: + encoding: UTF-8 + string: '' + headers: + User-Agent: + - SWD (1.3.0) (2.8.3, ruby 3.0.6 (2023-03-30)) + Accept: + - "*/*" + Date: + - Mon, 10 Apr 2023 18:16:56 GMT + response: + status: + code: 200 + message: OK + headers: + Date: + - Mon, 10 Apr 2023 18:16:56 GMT + Content-Length: + - '1347' + body: + encoding: UTF-8 + string: "{\r\n \"authorization_endpoint\": \"https://redacted-host/OAuth2/Authorize/redacted_app\",\r\n + \ \"code_challenge_methods_supported\": [\r\n \"plain\",\r\n \"S256\"\r\n + \ ],\r\n \"jwks_uri\": \"https://redacted-host/OAuth2/Keys/redacted_app\",\r\n + \ \"response_types_supported\": [\r\n \"code\",\r\n \"id_token\",\r\n + \ \"id_token token\",\r\n \"code id_token\",\r\n \"code token\",\r\n + \ \"code id_token token\"\r\n ],\r\n \"introspection_endpoint\": \"https://redacted-host/OAuth2/Introspect/redacted_app\",\r\n + \ \"id_token_signing_alg_values_supported\": [\r\n \"RS256\"\r\n ],\r\n + \ \"subject_types_supported\": [\r\n \"public\"\r\n ],\r\n \"issuer\": + \"https://redacted-host/redacted_app/\",\r\n \"userinfo_endpoint\": + \"https://redacted-host/OAuth2/UserInfo/redacted_app\",\r\n \"token_endpoint\": + \"https://redacted-host/OAuth2/Token/redacted_app\",\r\n \"scopes_supported\": + [\r\n \"openid\",\r\n \"profile\",\r\n \"email\",\r\n \"address\",\r\n + \ \"phone\"\r\n ],\r\n \"claims_supported\": [\r\n \"sub\",\r\n \"name\",\r\n + \ \"family_name\",\r\n \"given_name\",\r\n \"picture\",\r\n \"preferred_username\",\r\n + \ \"email\",\r\n \"email_verified\",\r\n \"phone_number\",\r\n \"phone_number_verified\",\r\n + \ \"address\",\r\n \"auth_time\",\r\n \"aud\",\r\n \"iss\",\r\n + \ \"exp\",\r\n \"iat\"\r\n ],\r\n \"end_session_endpoint\": \"https://redacted-host/OAuth2/EndSessionV2/redacted_app\"\r\n}" + recorded_at: Mon, 10 Apr 2023 18:16:56 GMT +recorded_with: VCR 6.1.0 diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-expired_code-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-expired_code-valid_oidc_credentials.yml similarity index 93% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-expired_code-valid_oidc_credentials.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-expired_code-valid_oidc_credentials.yml index 0607f2414c..9bfe2bdc39 100644 --- a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-expired_code-valid_oidc_credentials.yml +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-expired_code-valid_oidc_credentials.yml @@ -5,7 +5,7 @@ http_interactions: uri: https://dev-92899796.okta.com/oauth2/default/v1/token body: encoding: UTF-8 - string: grant_type=authorization_code&code=SNSPeiQJ0-D6nUHTg-Ht9ZoDxIaaWBB80pnYuXY2VxU&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d + string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&scope=true&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d headers: User-Agent: - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.4 (2022-04-12)) diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-invalid_code_verifier.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-invalid_code_verifier.yml similarity index 92% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-invalid_code_verifier.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-invalid_code_verifier.yml index 481657fb01..6902b6c383 100644 --- a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-invalid_code_verifier.yml +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-invalid_code_verifier.yml @@ -5,7 +5,7 @@ http_interactions: uri: https://dev-92899796.okta.com/oauth2/default/v1/token body: encoding: UTF-8 - string: grant_type=authorization_code&code=GV48_SF4a19ghvBhVbbSG3Lr8BuFl8PhWVPZSbokV2o&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&nonce=3e6bd5235e4692b37ca1f04cb01b6e0cb177aa20dcef19e89f&code_verifier=bad-code-verifier + string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&scope=true&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=bad-code-verifier headers: User-Agent: - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.4 (2022-04-12)) diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-used_code-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-used_code-valid_oidc_credentials.yml similarity index 96% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-used_code-valid_oidc_credentials.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-used_code-valid_oidc_credentials.yml index 83374a931a..2a3cc5d4b2 100644 --- a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-used_code-valid_oidc_credentials.yml +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-used_code-valid_oidc_credentials.yml @@ -5,7 +5,7 @@ http_interactions: uri: https://dev-92899796.okta.com/oauth2/default/v1/token body: encoding: UTF-8 - string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d + string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&scope=true&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d headers: User-Agent: - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.4 (2022-04-12)) diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-valid_oidc_credentials.yml similarity index 98% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-valid_oidc_credentials.yml index e837c8dce9..d0df4e7d8c 100644 --- a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_callback-valid_oidc_credentials.yml +++ b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_callback-valid_oidc_credentials.yml @@ -5,7 +5,7 @@ http_interactions: uri: https://dev-92899796.okta.com/oauth2/default/v1/token body: encoding: UTF-8 - string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d + string: grant_type=authorization_code&code=-QGREc_SONbbJIKdbpyYudA13c9PZlgqdxowkf45LOw&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthn-oidc%2Fokta-2%2Fcucumber%2Fauthenticate&scope=true&nonce=7efcbba36a9b96fdb5285a159665c3d382abd8b6b3288fcc8d&code_verifier=c1de7f1251849accd99d4839d79a637561b1181b909ed7dc1d headers: User-Agent: - Rack::OAuth2 (1.19.0) (2.8.3, ruby 3.0.4 (2022-04-12)) diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_initialization.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_initialization.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_initialization.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_initialization.yml diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_load.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_load.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/client_load.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/client_load.yml diff --git a/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/discovery_endpoint-valid_oidc_credentials.yml b/spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/discovery_endpoint-valid_oidc_credentials.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/discovery_endpoint-valid_oidc_credentials.yml rename to spec/fixtures/vcr_cassettes/authenticators/authn-oidc/v2/okta-2/discovery_endpoint-valid_oidc_credentials.yml From 8147acf879704f486a66ff11ed1374fa72a8745c Mon Sep 17 00:00:00 2001 From: Neil King Date: Mon, 8 May 2023 09:44:27 -0700 Subject: [PATCH 31/42] Support running cucumber tests in parallel: - Spawn multiple processes to execute cucumber tests in parallel. Each process contains it's own indipendent conjur instance and postgresql database to avoid colisions. - Dynamically alter Ruby ENV variables based on the process executing the cucumber feature tests. - Dockerfile has been altered to support replicated services for parallel tests (this has not been altered to be dynamic and consists of static changes). - Alter cucumber.yml profiles to support parallel_tests ruby gem cmd usage The following tests have not been parallelized: - authenticators_k8s - rspec tests --- Gemfile | 1 + Gemfile.lock | 3 + Jenkinsfile | 429 +++++++++++++++--- ci/docker-compose.yml | 70 ++- ci/oauth/keycloak/keycloak_functions.sh | 14 +- ci/shared.sh | 103 ++++- ci/test | 5 +- ci/test_suites/authenticators_jwt/test | 4 +- ci/test_suites/authenticators_oidc/test | 4 +- ci/test_suites/rotators/test | 13 +- config/environments/development.rb | 4 +- config/environments/test.rb | 11 + cucumber.yml | 14 +- .../features/support/authenticator_helpers.rb | 2 +- .../features/support/env.rb | 13 +- .../features/support/hooks.rb | 9 + cucumber/api/features/support/env.rb | 11 + cucumber/api/features/support/hooks.rb | 9 + .../authenticators/features/support/hooks.rb | 9 + .../features/authn_jwt_token_schema.feature | 12 +- .../features/support/env.rb | 11 + .../features/support/hooks.rb | 9 + cucumber/policy/features/support/client.rb | 2 +- cucumber/policy/features/support/env.rb | 13 +- cucumber/policy/features/support/hooks.rb | 9 + .../step_definitions/rotator_steps.rb | 3 + cucumber/rotators/features/support/env.rb | 13 +- .../features/support/rotator_helpers.rb | 4 +- engines/conjur_audit/config/routes.rb | 11 + .../spec/dummy/config/environments/test.rb | 11 + 30 files changed, 709 insertions(+), 117 deletions(-) diff --git a/Gemfile b/Gemfile index 7908f2c6ff..892a5833e1 100644 --- a/Gemfile +++ b/Gemfile @@ -92,6 +92,7 @@ group :development, :test do gem 'faye-websocket' gem 'net-ssh' gem 'parallel' + gem 'parallel_tests' gem 'pry-byebug' gem 'pry-rails' gem 'rails-controller-testing' diff --git a/Gemfile.lock b/Gemfile.lock index 5849b1b8d1..94dba54f9f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -317,6 +317,8 @@ GEM validate_url webfinger (>= 1.0.1) parallel (1.21.0) + parallel_tests (4.2.0) + parallel parser (3.0.3.2) ast (~> 2.4.1) pg (1.2.3) @@ -551,6 +553,7 @@ DEPENDENCIES nokogiri (>= 1.8.2) openid_connect parallel + parallel_tests pg pry-byebug pry-rails diff --git a/Jenkinsfile b/Jenkinsfile index cef3cd441e..e441466409 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -77,6 +77,10 @@ if (params.MODE == "PROMOTE") { return } +// Break the total number of tests into a subset of tests. +// This will give 3 nested lists of tests to run, which is +// distributed over 3 jenkins agents. +def NESTED_ARRAY_OF_TESTS_TO_RUN = collateTests() pipeline { agent { label 'executor-v2' } @@ -277,98 +281,282 @@ pipeline { when { expression { params.NIGHTLY } } + agent { label 'executor-v2-rhel-ee' } environment { CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" } stages { - stage('EE FIPS agent tests') { - agent { label 'executor-v2-rhel-ee' } + stage("RSpec - EE FIPS agent tests") { steps { sh(script: 'cat /etc/os-release', label: 'RHEL version') sh(script: 'docker --version', label: 'Docker version') + addNewImagesToAgent() unstash 'version_info' // Catch errors so remaining steps always run. catchError { // Run outside parallel block to avoid external pressure - script { - stage("RSpec - EE FIPS agent tests") { - sh "ci/test rspec" + sh "ci/test rspec" + } + } + } + + stage('EE FIPS parallel') { + parallel { + stage('EE FIPS agent tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[0]) + ) } } - runConjurTests(params.RUN_ONLY) + steps { + addNewImagesToAgent() + unstash 'version_info' + runConjurTests( + params.RUN_ONLY, + NESTED_ARRAY_OF_TESTS_TO_RUN[0] + ) + stash( + name: 'testResultEE', + includes: ''' + cucumber/*/*.*, + container_logs/*/*, + spec/reports/*.xml, + spec/reports-audit/*.xml, + gems/conjur-rack/spec/reports/*.xml, + cucumber/*/features/reports/**/*.xml + ''' + ) + } } + // Run a subset of tests on a second agent to prevent oversubscribing the hardware + stage('EE FIPS agent2 tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[1]) + ) + } + } + agent { label 'executor-v2-rhel-ee' } - stash( - name: 'testResultEE', - includes: ''' - cucumber/*/*.*, - container_logs/*/*, - spec/reports/*.xml, - spec/reports-audit/*.xml, - gems/conjur-rack/spec/reports/*.xml, - cucumber/*/features/reports/**/*.xml - ''' - ) - } + environment { + CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" + } - post { - always { - dir('ee-test'){ - unstash 'testResultEE' + steps { + addNewImagesToAgent() + unstash 'version_info' + runConjurTests( + params.RUN_ONLY, + NESTED_ARRAY_OF_TESTS_TO_RUN[1] + ) + stash( + name: 'testResultEE2', + includes: ''' + cucumber/*/*.*, + container_logs/*/*, + spec/reports/*.xml, + spec/reports-audit/*.xml, + cucumber/*/features/reports/**/*.xml + ''' + ) + } + } + // Run a subset of tests on a second agent to prevent oversubscribing the hardware + stage('EE FIPS agent3 tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[2]) + ) + } } - archiveArtifacts( - artifacts: "ee-test/cucumber/*/*.*", - fingerprint: false, - allowEmptyArchive: true - ) + agent { label 'executor-v2-rhel-ee' } - archiveArtifacts( - artifacts: "ee-test/container_logs/*/*", - fingerprint: false, - allowEmptyArchive: true - ) + environment { + CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" + } - publishHTML( - reportDir: 'ee-test/cucumber', - reportFiles: ''' - api/cucumber_results.html, - authenticators_config/cucumber_results.html, - authenticators_azure/cucumber_results.html, - authenticators_ldap/cucumber_results.html, - authenticators_oidc/cucumber_results.html, - authenticators_jwt/cucumber_results.html, - authenticators_status/cucumber_results.html - policy/cucumber_results.html, - rotators/cucumber_results.html - ''', - reportName: 'EE Integration reports', - reportTitles: '', - allowMissing: false, - alwaysLinkToLastBuild: true, - keepAll: true - ) + steps { + addNewImagesToAgent() + unstash 'version_info' + runConjurTests( + params.RUN_ONLY, + NESTED_ARRAY_OF_TESTS_TO_RUN[2] + ) + stash( + name: 'testResultEE3', + includes: ''' + cucumber/*/*.*, + container_logs/*/*, + spec/reports/*.xml, + spec/reports-audit/*.xml, + cucumber/*/features/reports/**/*.xml + ''' + ) + } } } } } + post { + always { + script { + if (testShouldRunOnAgent(params.RUN_ONLY, runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[0]))) { + dir('ee-test'){ + unstash 'testResultEE' + } + } + if (testShouldRunOnAgent(params.RUN_ONLY, runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[1]))) { + dir('ee-test'){ + unstash 'testResultEE2' + } + } + if (testShouldRunOnAgent(params.RUN_ONLY, runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[2]))) { + dir('ee-test'){ + unstash 'testResultEE3' + } + } + } + + archiveArtifacts( + artifacts: "ee-test/cucumber/*/*.*", + fingerprint: false, + allowEmptyArchive: true + ) + + archiveArtifacts( + artifacts: "ee-test/container_logs/*/*", + fingerprint: false, + allowEmptyArchive: true + ) + + publishHTML( + reportDir: 'ee-test/cucumber', + reportFiles: ''' + api/cucumber_results.html, + authenticators_config/cucumber_results.html, + authenticators_azure/cucumber_results.html, + authenticators_ldap/cucumber_results.html, + authenticators_oidc/cucumber_results.html, + authenticators_jwt/cucumber_results.html, + authenticators_status/cucumber_results.html + policy/cucumber_results.html, + rotators/cucumber_results.html + ''', + reportName: 'EE Integration reports', + reportTitles: '', + allowMissing: false, + alwaysLinkToLastBuild: true, + keepAll: true + ) + } + } } stage('Run environment tests in parallel') { parallel { stage('Standard agent tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[0]) + ) + } + } + environment { CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" } steps { - sh(script: 'cat /etc/os-release', label: 'RHEL version') + sh(script: 'cat /etc/os-release', label: 'Ubuntu version') sh(script: 'docker --version', label: 'Docker version') - runConjurTests(params.RUN_ONLY) + runConjurTests( + params.RUN_ONLY, + NESTED_ARRAY_OF_TESTS_TO_RUN[0] + ) + } + } + + // Run a subset of tests on a second agent to prevent oversubscribing the hardware + stage('Standard agent2 tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[1]) + ) + } + } + + agent { label 'executor-v2' } + environment { + CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" + } + + steps { + addNewImagesToAgent() + unstash 'version_info' + runConjurTests(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[1]) + stash( + name: 'standardTestResult2', + includes: ''' + cucumber/*/*.*, + container_logs/*/*, + spec/reports/*.xml, + spec/reports-audit/*.xml, + cucumber/*/features/reports/**/*.xml + ''' + ) + } + } + + // Run a subset of tests on a second agent to prevent oversubscribing the hardware + stage('Standard agent3 tests') { + when { + expression { + testShouldRunOnAgent( + params.RUN_ONLY, + runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[2]) + ) + } + } + + agent { label 'executor-v2' } + environment { + CUCUMBER_FILTER_TAGS = "${params.CUCUMBER_FILTER_TAGS}" + } + + steps { + addNewImagesToAgent() + unstash 'version_info' + runConjurTests( + params.RUN_ONLY, + NESTED_ARRAY_OF_TESTS_TO_RUN[2] + ) + stash( + name: 'standardTestResult3', + includes: ''' + cucumber/*/*.*, + container_logs/*/*, + spec/reports/*.xml, + spec/reports-audit/*.xml, + cucumber/*/features/reports/**/*.xml, + ci/test_suites/*/output/* + ''' + ) } } @@ -396,6 +584,7 @@ pipeline { } steps { + addNewImagesToAgent() unstash 'version_info' // Grant access to this Jenkins agent's IP to AWS security groups // This is required for access to the internal docker registry @@ -626,6 +815,14 @@ pipeline { always { script { + if (testShouldRunOnAgent(params.RUN_ONLY, runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[1]))) { + unstash 'standardTestResult2' + } + + if (testShouldRunOnAgent(params.RUN_ONLY, runSpecificTestOnAgent(params.RUN_ONLY, NESTED_ARRAY_OF_TESTS_TO_RUN[2]))) { + unstash 'standardTestResult3' + } + // Only unstash azure if it ran. if (testShouldRun(params.RUN_ONLY, "azure_authenticator")) { unstash 'testResultAzure' @@ -751,12 +948,24 @@ pipeline { // TODO: Do we want to move any of these functions to a separate file? +def addNewImagesToAgent() { + // Pull and retag existing images onto new Jenkins agent + sh """ + docker pull registry.tld/conjur:${tagWithSHA()} + docker pull registry.tld/conjur-ubi:${tagWithSHA()} + docker pull registry.tld/conjur-test:${tagWithSHA()} + docker tag registry.tld/conjur:${tagWithSHA()} conjur:${tagWithSHA()} + docker tag registry.tld/conjur-ubi:${tagWithSHA()} conjur-ubi:${tagWithSHA()} + docker tag registry.tld/conjur-test:${tagWithSHA()} conjur-test:${tagWithSHA()} + """ +} + // Possible minor optimization: Could memoize this. Need to verify it's not // shared across builds. def tagWithSHA() { sh( returnStdout: true, - script: 'echo $(git rev-parse --short=8 HEAD)' + script: 'echo -n $(git rev-parse --short=8 HEAD)' ) } @@ -772,11 +981,37 @@ def testShouldRun(run_only_str, test) { return run_only_str == '' || run_only_str.split().contains(test) } -// "run_only_str" is a space-separated string specifying the subset of tests to -// run. If it's empty, all tests are run. -def runConjurTests(run_only_str) { +def testShouldRunOnAgent(run_only_str, agent_specific_tests) { + return run_only_str == '' || ! agent_specific_tests.isEmpty() +} + +def runSpecificTestOnAgent(run_only_str, agent_specific_tests) { + // runSpecificTestOnAgent allows a subset of tests to be ran + // on an agent, determined by the agent's assigned subset of + // tests it normally runs. + + // Args: + // run_only_str: a space seperated string of test names + // agent_specific_tests: an array of tests that the agent + // is assigned to run + + // Returns: + // An array of test names to run + def run_only_tests = [] + def find_tests = run_only_str.split() + + find_tests.each { run_only_test -> + agent_specific_tests.find { agent_test -> + if (agent_test.contains(run_only_test)) { + run_only_tests.add(run_only_test) + } + } + } + return run_only_tests +} - all_tests = [ +def conjurTests() { + return [ "authenticators_config": [ "Authenticators Config - ${env.STAGE_NAME}": { sh 'ci/test authenticators_config' @@ -787,16 +1022,16 @@ def runConjurTests(run_only_str) { sh 'ci/test authenticators_status' } ], - "authenticators_k8s": [ - "K8s Authenticator - ${env.STAGE_NAME}": { - sh 'ci/test authenticators_k8s' - } - ], "authenticators_ldap": [ "LDAP Authenticator - ${env.STAGE_NAME}": { sh 'ci/test authenticators_ldap' } ], + "api": [ + "API - ${env.STAGE_NAME}": { + sh 'ci/test api' + } + ], "authenticators_oidc": [ "OIDC Authenticator - ${env.STAGE_NAME}": { sh 'summon -f ./ci/test_suites/authenticators_oidc/secrets.yml -e ci ci/test authenticators_oidc' @@ -812,16 +1047,16 @@ def runConjurTests(run_only_str) { sh 'ci/test policy' } ], - "api": [ - "API - ${env.STAGE_NAME}": { - sh 'ci/test api' - } - ], "rotators": [ "Rotators - ${env.STAGE_NAME}": { sh 'ci/test rotators' } ], + "authenticators_k8s": [ + "K8s Authenticator - ${env.STAGE_NAME}": { + sh 'ci/test authenticators_k8s' + } + ], "rspec_audit": [ "Audit - ${env.STAGE_NAME}": { sh 'ci/test rspec_audit' @@ -838,13 +1073,26 @@ def runConjurTests(run_only_str) { } ] ] +} + +def runConjurTests(run_only_str, cuke_test_names) { + // runConjurTests will build a parallel Jenkins block of code + // that will run the specified cucumber test stages. - // Filter for the tests we want run, if requested. - parallel_tests = all_tests - tests = run_only_str.split() + // Args: + // cuke_test_names an array of test names to run. - if (tests.size() > 0) { - parallel_tests = all_tests.subMap(tests) + // Returns: + // A Jenkins block of parallel code. + + def all_tests = conjurTests() + def run_only_tests = runSpecificTestOnAgent(run_only_str, cuke_test_names) + def parallel_tests = all_tests + + if (run_only_tests.isEmpty()) { + parallel_tests = all_tests.subMap(cuke_test_names) + } else { + parallel_tests = all_tests.subMap(run_only_tests) } // Create the parallel pipeline. @@ -852,6 +1100,7 @@ def runConjurTests(run_only_str) { // Since + merges two maps together, sum() combines the individual values of // parallel_tests into one giant map whose keys are the stage names and // whose values are the blocks to be run. + script { parallel( parallel_tests.values().sum() @@ -859,6 +1108,40 @@ def runConjurTests(run_only_str) { } } +def collateTests(jobs_per_agent=4) { + // collateTests will find the names of cucumber tests that should run + // and create a nested list of tests to be ran across mutliple Jenkins + // agents. + + // Args: + // jobs_per_agent: The nested list of tests names will be no more than + // the specified integer. + + // Returns: a nested list of test names. + + def all_tests = conjurTests() + def all_test_names = [] + + all_tests.each{ k, _ -> + all_test_names.add(k) + } + + def parallel_tests = [] + // Create a subset of tests that can be ran by each Jenkins agent + int partitionCount = all_test_names.size() / jobs_per_agent + + partitionCount.times { partitionNumber -> + def start = partitionNumber * jobs_per_agent + def end = start + jobs_per_agent - 1 + parallel_tests.add(all_test_names[start..end]) + } + + if (all_tests.size() % jobs_per_agent) { + parallel_tests.add(all_test_names[partitionCount * jobs_per_agent..-1]) + } + return parallel_tests +} + def defaultCucumberFilterTags(env) { if(env.BRANCH_NAME == 'master' || env.TAG_NAME?.trim()) { // If this is a master or tag build, we want to run all of the tests. So diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index 38f4c67de1..47754bafda 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -14,6 +14,20 @@ services: # PostgreSQL documentation about "trust" POSTGRES_HOST_AUTH_METHOD: trust + pg2: + image: postgres:10.16 + environment: + # To avoid the following error: + # + # Error: Database is uninitialized and superuser password is not + # specified. You must specify POSTGRES_PASSWORD for the superuser. Use + # "-e POSTGRES_PASSWORD=password" to set it in "docker run". + # + # You may also use POSTGRES_HOST_AUTH_METHOD=trust to allow all + # connections without a password. This is *not* recommended. See + # PostgreSQL documentation about "trust" + POSTGRES_HOST_AUTH_METHOD: trust + audit: image: postgres:10.16 environment: @@ -34,6 +48,20 @@ services: # PostgreSQL documentation about "trust" POSTGRES_HOST_AUTH_METHOD: trust + testdb2: + image: postgres:10.16 + environment: + # To avoid the following error: + # + # Error: Database is uninitialized and superuser password is not + # specified. You must specify POSTGRES_PASSWORD for the superuser. Use + # "-e POSTGRES_PASSWORD=password" to set it in "docker run". + # + # You may also use POSTGRES_HOST_AUTH_METHOD=trust to allow all + # connections without a password. This is *not* recommended. See + # PostgreSQL documentation about "trust" + POSTGRES_HOST_AUTH_METHOD: trust + conjur: image: "conjur-test:${TAG}" environment: @@ -67,14 +95,45 @@ services: - ldap-server - keycloak + conjur2: + image: "conjur-test:${TAG}" + environment: + DATABASE_URL: postgres://postgres@pg2/postgres + CONJUR_ADMIN_PASSWORD: ADmin123!!!! + CONJUR_ACCOUNT: cucumber + CONJUR_DATA_KEY: + RAILS_ENV: + REQUIRE_SIMPLECOV: "true" + CONJUR_LOG_LEVEL: debug + CONJUR_AUTHENTICATORS: authn-ldap/test,authn-ldap/secure,authn-oidc/keycloak,authn-oidc,authn-k8s/test,authn-azure/prod,authn-gcp,authn-jwt/raw,authn-jwt/keycloak,authn-oidc/keycloak2,authn-oidc/okta-2 + LDAP_URI: ldap://ldap-server:389 + LDAP_BASE: dc=conjur,dc=net + LDAP_FILTER: '(uid=%s)' + LDAP_BINDDN: cn=admin,dc=conjur,dc=net + LDAP_BINDPW: ldapsecret + WEB_CONCURRENCY: 0 + RAILS_MAX_THREADS: 10 + command: server + volumes: + # TODO: authenticators_oidc/test has a dep on this + - authn-local2:/run/authn-local + - ./oauth/keycloak:/oauth/keycloak/scripts + - ./ldap-certs:/ldap-certs:ro + - log-volume:/opt/conjur-server/log + - ../coverage:/opt/conjur-server/coverage + expose: + - "80" + links: + - pg2 + - ldap-server + - keycloak + cucumber: image: conjur-test:$TAG entrypoint: bash working_dir: /src/conjur-server environment: - CONJUR_APPLIANCE_URL: http://conjur CONJUR_ACCOUNT: cucumber - DATABASE_URL: postgres://postgres@pg/postgres AUDIT_DATABASE_URL: RAILS_ENV: test CONJUR_LOG_LEVEL: debug @@ -88,14 +147,18 @@ services: volumes: - ..:/src/conjur-server - authn-local:/run/authn-local + - authn-local2:/run/authn-local - ./ldap-certs:/ldap-certs:ro - log-volume:/src/conjur-server/log - jwks-volume:/var/jwks - ./oauth/keycloak:/oauth/keycloak/scripts links: - conjur + - conjur2 - pg + - pg2 - testdb + - testdb2 - keycloak ldap-server: @@ -168,5 +231,6 @@ services: volumes: authn-local: + authn-local2: log-volume: - jwks-volume: \ No newline at end of file + jwks-volume: diff --git a/ci/oauth/keycloak/keycloak_functions.sh b/ci/oauth/keycloak/keycloak_functions.sh index c01216f1d8..dada055816 100644 --- a/ci/oauth/keycloak/keycloak_functions.sh +++ b/ci/oauth/keycloak/keycloak_functions.sh @@ -2,6 +2,10 @@ KEYCLOAK_SERVICE_NAME="keycloak" +# This is executed by the main "ci/test" script after cd-ing into "ci". +# shellcheck disable=SC1091 +source "./shared.sh" + # Note: the single arg is a nameref, which this function sets to an array # containing items of the form "KEY=VAL". function _hydrate_keycloak_env_args() { @@ -84,6 +88,12 @@ function fetch_keycloak_certificate() { # there's a dep on the docker-compose.yml volumes. # Fetch SSL cert to communicate with keycloak (OIDC provider). echo "Initialize keycloak certificate in conjur server" - docker-compose exec -T \ - conjur /oauth/keycloak/scripts/fetch_certificate + + local parallel_services + read -ra parallel_services <<< "$(get_parallel_services 'conjur')" + + for parallel_service in "${parallel_services[@]}"; do + docker-compose exec -T \ + "${parallel_service}" /oauth/keycloak/scripts/fetch_certificate + done } diff --git a/ci/shared.sh b/ci/shared.sh index 5de62b47bc..537c831613 100644 --- a/ci/shared.sh +++ b/ci/shared.sh @@ -2,6 +2,38 @@ export REPORT_ROOT=/src/conjur-server +# Sets the number of parallel processes for cucumber tests +# Due to naming conventions for parallel_cucumber this begins at 1 NOT 0 +PARALLEL_PROCESSES=2 + +get_parallel_services() { + # get_parallel_services converts docker service names + # to the appropriate naming conventions expected for + # parallel cucumber tests. + + # Args: + # $1: A string of space delimited docker service name(s) + + # Returns: + # An array of docker service names matching the expected + # parallel cucumber naming convention. + local services + local parallel_services + read -ra services <<< "$1" + + for service in "${services[@]}"; do + for (( i=1; i<=PARALLEL_PROCESSES; i++ )); do + if (( i == 1 )) ; then + parallel_services+=("$service") + else + parallel_services+=("$service${i}") + fi + done + done + + echo "${parallel_services[@]}" +} + # Note: This function is long but purposefully not split up. None of its parts # are re-used, and the split-up version is harder to follow and duplicates # argument processing. @@ -30,12 +62,25 @@ _run_cucumber_tests() { echo "Start all services..." - docker-compose up --no-deps --no-recreate -d pg conjur "${services[@]}" - docker-compose exec -T conjur conjurctl wait --retries 180 + local parallel_services + read -ra parallel_services <<< "$(get_parallel_services 'conjur pg')" + + if (( ${#services[@]} )); then + docker-compose up --no-deps --no-recreate -d "${parallel_services[@]}" "${services[@]}" + else + docker-compose up --no-deps --no-recreate -d "${parallel_services[@]}" + fi + + read -ra parallel_services <<< "$(get_parallel_services 'conjur')" + for parallel_service in "${parallel_services[@]}"; do + docker-compose exec -T "$parallel_service" conjurctl wait --retries 180 + done echo "Create cucumber account..." - docker-compose exec -T conjur conjurctl account create cucumber + for parallel_service in "${parallel_services[@]}"; do + docker-compose exec -T "$parallel_service" conjurctl account create cucumber + done # Stage 2: Prepare cucumber environment args # ----------------------------------------------------------- @@ -56,16 +101,31 @@ _run_cucumber_tests() { env_var_flags+=(-e "$item") done + # Generate api key ENV variables based on the + # number of parallel processes. + for (( i=1; i <= ${#parallel_services[@]}; ++i )); do + index=$(( i - 1 )) + if (( i == 1 )) ; then + api_keys+=("CONJUR_AUTHN_API_KEY=$(_get_api_key "${parallel_services[$index]}")") + else + api_keys+=("CONJUR_AUTHN_API_KEY${i}=$(_get_api_key "${parallel_services[$index]}")") + fi + done + # Add the cucumber env vars that we always want to send. # Note: These are args for docker-compose run, and as such the right hand # sides of the = do NOT require escaped quotes. docker-compose takes the # entire arg, splits on the =, and uses the rhs as the value, env_var_flags+=( - -e "CONJUR_AUTHN_API_KEY=$(_get_api_key)" -e "CUCUMBER_NETWORK=$(_find_cucumber_network)" -e "CUCUMBER_FILTER_TAGS=$CUCUMBER_FILTER_TAGS" ) + # Add parallel process api_keys to the env_var_flags + for api_key in "${api_keys[@]}"; do + env_var_flags+=(-e "$api_key") + done + # If there's no tty (e.g. we're running as a Jenkins job), pass -T to # docker-compose. run_flags=(--no-deps --rm) @@ -84,16 +144,23 @@ _run_cucumber_tests() { # Stage 3: Run Cucumber # ----------------------------------------------------------- + echo "ENV_ARG_FN: ${env_arg_fn}" >&2 + echo "RUN_FLAGS: ${run_flags[*]}" >&2 + echo "ENV_VAR_FLAGS: ${env_var_flags[*]}" >&2 + echo "CUCUMBER TAGS: ${cucumber_tags_arg}" >&2 + echo "CUCUMBER PROFILE: ${profile}" >&2 + + + # Have to add tags in profile for parallel to run properly + # ${cucumber_tags_arg} should overwrite the profile tags in a way for @smoke to work correctly docker-compose run "${run_flags[@]}" "${env_var_flags[@]}" \ cucumber -ec "\ /oauth/keycloak/scripts/fetch_certificate && - bundle exec cucumber \ - --strict \ - ${cucumber_tags_arg} \ - -p \"$profile\" \ + bundle exec parallel_cucumber . -n ${PARALLEL_PROCESSES} \ + -o '--strict --profile \"${profile}\" ${cucumber_tags_arg} \ --format json --out \"cucumber/$profile/cucumber_results.json\" \ --format html --out \"cucumber/$profile/cucumber_results.html\" \ - --format junit --out \"cucumber/$profile/features/reports\"" + --format junit --out \"cucumber/$profile/features/reports\"'" # Stage 4: Coverage results # ----------------------------------------------------------- @@ -102,21 +169,26 @@ _run_cucumber_tests() { # killed before ruby, the report doesn't get written. So here we kill the # process to write the report. The container is kept alive using an infinite # sleep in the at_exit hook (see .simplecov). - docker-compose exec -T conjur bash -c "pkill -f 'puma 5'" + for parallel_service in "${parallel_services[@]}"; do + docker-compose exec -T "$parallel_service" bash -c "pkill -f 'puma 5'" + done } _get_api_key() { - docker-compose exec -T conjur conjurctl \ + local service=$1 + + docker-compose exec -T "${service}" conjurctl \ role retrieve-key cucumber:user:admin | tr -d '\r' } _find_cucumber_network() { local net - net=$( - docker inspect "$(docker-compose ps -q conjur)" \ - --format '{{.HostConfig.NetworkMode}}' - ) + # Docker compose conjur/pg services use the same + # network for 1 or more instances so only conjur is passed + # and not other parallel services. + conjur_id=$(docker-compose ps -q conjur) + net=$(docker inspect "${conjur_id}" --format '{{.HostConfig.NetworkMode}}') docker network inspect "$net" \ --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' @@ -180,5 +252,6 @@ start_ldap_server() { echo 'LDAP server failed to start in time' exit 1 fi + echo "Done." } diff --git a/ci/test b/ci/test index cc99051be8..0ba14cbabb 100755 --- a/ci/test +++ b/ci/test @@ -86,9 +86,8 @@ docker_diagnostics() { # its _value_ in the regex. # # Docker Note: container name is always the last field. Hence $NF gets it. - readarray -t cont_names < <( - docker ps --all | awk "/${COMPOSE_PROJECT_NAME}/{print \$NF}" - ) + declare -a cont_names + while IFS=$'\n' read -r line; do cont_names+=("$line"); done < <(docker ps --all | awk "/${COMPOSE_PROJECT_NAME}/{print \$NF}") # Store container logs for archiving. echo "Writing Container logs to" \ diff --git a/ci/test_suites/authenticators_jwt/test b/ci/test_suites/authenticators_jwt/test index e3611a7b2b..db1a27a949 100755 --- a/ci/test_suites/authenticators_jwt/test +++ b/ci/test_suites/authenticators_jwt/test @@ -8,7 +8,9 @@ source "./shared.sh" source "./oauth/keycloak/keycloak_functions.sh" function main() { - docker-compose up --no-deps -d pg conjur jwks jwks_py keycloak + local parallel_services + read -ra parallel_services <<< "$(get_parallel_services 'conjur pg')" + docker-compose up --no-deps -d "${parallel_services[@]}" jwks jwks_py keycloak wait_for_keycloak_server create_keycloak_users diff --git a/ci/test_suites/authenticators_oidc/test b/ci/test_suites/authenticators_oidc/test index b2508a5143..bea0f8bc48 100755 --- a/ci/test_suites/authenticators_oidc/test +++ b/ci/test_suites/authenticators_oidc/test @@ -36,7 +36,9 @@ function _hydrate_all_env_args() { } function main() { - docker-compose up --no-deps -d pg conjur keycloak + local parallel_services + read -ra parallel_services <<< "$(get_parallel_services 'conjur pg')" + docker-compose up --no-deps -d "${parallel_services[@]}" keycloak # We also run an ldap-server container for testing the OIDC & LDAP combined # use-case. We can't run this use-case in a separate Jenkins step because diff --git a/ci/test_suites/rotators/test b/ci/test_suites/rotators/test index 20b2634b81..badf62fa37 100755 --- a/ci/test_suites/rotators/test +++ b/ci/test_suites/rotators/test @@ -5,5 +5,14 @@ set -e # shellcheck disable=SC1091 source "./shared.sh" -additional_services='testdb' -_run_cucumber_tests rotators "$additional_services" +read -ra parallel_services <<< "$(get_parallel_services 'testdb')" +additional_services='' +for service in "${parallel_services[@]}"; do + if [[ "$additional_services" == '' ]]; then + additional_services+="${service}" + else + additional_services+=" ${service}" + fi +done + +_run_cucumber_tests rotators "${additional_services}" diff --git a/config/environments/development.rb b/config/environments/development.rb index c7a29d77cd..d3b9a48acb 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,7 +13,9 @@ # Whitelist conjur hostname for tests # For more information, refer to: # https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization - config.hosts << "conjur" + + # Accept multiple hosts for parallel tests + config.hosts << /^conjur[0-9]*$/ # eager_load needed to make authentication work without the hacky # loading code... diff --git a/config/environments/test.rb b/config/environments/test.rb index 26ea1a7b1d..db8a6d08dd 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -3,6 +3,17 @@ require 'logger/formatter/conjur_formatter' require 'test/audit_sink' +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/cucumber.yml b/cucumber.yml index 67b3d17cf5..f3c4378b5e 100644 --- a/cucumber.yml +++ b/cucumber.yml @@ -1,9 +1,11 @@ policy: > + --tags @policy --format pretty -r cucumber/policy cucumber/policy api: > + --tags @api --format pretty -r cucumber/api/features/support/logs_helpers.rb -r cucumber/api/features/step_definitions/logs_steps.rb @@ -20,6 +22,7 @@ api: > # directory is above it (e.g authenticators_azure is above authenticators_common) # then we will not be able to load the methods defined in authenticators_common authenticators_config: > + --tags @authenticators_config --format pretty -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -34,6 +37,7 @@ authenticators_config: > cucumber/authenticators_config authenticators_status: > + --tags @authenticators_status --format pretty -r cucumber/api/features/support/rest_helpers.rb -r cucumber/api/features/support/step_def_transforms.rb @@ -50,6 +54,7 @@ authenticators_status: > cucumber/authenticators_status authenticators_ldap: > + --tags @authenticators_ldap --format pretty -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -66,6 +71,7 @@ authenticators_ldap: > cucumber/authenticators_ldap authenticators_oidc: > + --tags @authenticators_oidc --format pretty -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -87,6 +93,7 @@ authenticators_oidc: > cucumber/authenticators_oidc authenticators_gcp: > + --tags @authenticators_gcp --format pretty -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -105,6 +112,7 @@ authenticators_gcp: > cucumber/authenticators_gcp authenticators_azure: > + --tags @authenticators_azure --format pretty -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -123,8 +131,8 @@ authenticators_azure: > cucumber/authenticators_azure authenticators_jwt: > + --tags "not @skip and @authenticators_jwt" --format pretty - --tags "not @skip" -r cucumber/api/features/step_definitions/user_steps.rb -r cucumber/api/features/step_definitions/request_steps.rb -r cucumber/api/features/support/step_def_transforms.rb @@ -148,8 +156,8 @@ authenticators_jwt: > # profiles need to be thought through better and refactored most likely. # rotators: > + --tags 'not @manual and @rotators' --format pretty - -t 'not @manual' -r cucumber/authenticators/features/support/hooks.rb -r cucumber/api/features/support/step_def_transforms.rb -r cucumber/api/features/support/rest_helpers.rb @@ -161,8 +169,8 @@ rotators: > cucumber/rotators manual-rotators: > - --format pretty --tags @manual + --format pretty -r cucumber/rotators/features/support -r cucumber/rotators/features/step_definitions cucumber/rotators diff --git a/cucumber/_authenticators_common/features/support/authenticator_helpers.rb b/cucumber/_authenticators_common/features/support/authenticator_helpers.rb index e460bffa12..986c633bcc 100644 --- a/cucumber/_authenticators_common/features/support/authenticator_helpers.rb +++ b/cucumber/_authenticators_common/features/support/authenticator_helpers.rb @@ -104,7 +104,7 @@ def execute(method, path, payload = {}, options = {}) end def conjur_hostname - ENV.fetch('CONJUR_APPLIANCE_URL', 'http://conjur') + ENV.fetch('CONJUR_APPLIANCE_URL', "http://conjur#{ENV['TEST_ENV_NUMBER']}") end private diff --git a/cucumber/_authenticators_common/features/support/env.rb b/cucumber/_authenticators_common/features/support/env.rb index ccaeaf8735..35f864e9f1 100644 --- a/cucumber/_authenticators_common/features/support/env.rb +++ b/cucumber/_authenticators_common/features/support/env.rb @@ -1,5 +1,16 @@ # frozen_string_literal: true +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + $LOAD_PATH.unshift(Dir.pwd) require 'config/environment' @@ -9,5 +20,5 @@ require 'conjur-api' require 'json_spec/cucumber' -Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || 'http://conjur' +Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || "http://conjur#{ENV['TEST_ENV_NUMBER']}" Conjur.configuration.account = ENV['CONJUR_ACCOUNT'] || 'cucumber' diff --git a/cucumber/_authenticators_common/features/support/hooks.rb b/cucumber/_authenticators_common/features/support/hooks.rb index bc93541569..08d641f6fc 100644 --- a/cucumber/_authenticators_common/features/support/hooks.rb +++ b/cucumber/_authenticators_common/features/support/hooks.rb @@ -9,6 +9,15 @@ # Prior to this hook, our tests had hidden coupling. This ensures each test is # run independently. Before do + parallel_cuke_vars = {} + parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" + parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" + parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + + parallel_cuke_vars.each do |key, value| + ENV[key] = value + end + @user_index = 0 @host_index = 0 diff --git a/cucumber/api/features/support/env.rb b/cucumber/api/features/support/env.rb index edabb5a5db..5d47c8df2d 100644 --- a/cucumber/api/features/support/env.rb +++ b/cucumber/api/features/support/env.rb @@ -4,6 +4,17 @@ ENV['RAILS_ENV'] ||= 'test' ENV['CONJUR_LOG_LEVEL'] ||= 'debug' +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + # so that we can require relative to the project root $LOAD_PATH.unshift(File.expand_path('../../../..', __dir__)) require 'config/environment' diff --git a/cucumber/api/features/support/hooks.rb b/cucumber/api/features/support/hooks.rb index 4e47f2f2ef..90c785d26c 100644 --- a/cucumber/api/features/support/hooks.rb +++ b/cucumber/api/features/support/hooks.rb @@ -10,6 +10,15 @@ # Prior to this hook, our tests had hidden coupling. This ensures each test is # run independently. Before do + parallel_cuke_vars = {} + parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" + parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" + parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + + parallel_cuke_vars.each do |key, value| + ENV[key] = value + end + @user_index = 0 @host_index = 0 diff --git a/cucumber/authenticators/features/support/hooks.rb b/cucumber/authenticators/features/support/hooks.rb index 6c164a773d..46c551b9ee 100644 --- a/cucumber/authenticators/features/support/hooks.rb +++ b/cucumber/authenticators/features/support/hooks.rb @@ -5,6 +5,15 @@ # Prior to this hook, our tests had hidden coupling. This ensures each test is # run independently. Before do + parallel_cuke_vars = {} + parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" + parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" + parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + + parallel_cuke_vars.each do |key, value| + ENV[key] = value + end + @user_index = 0 Role.truncate(cascade: true) diff --git a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature index a8c523707f..cb422b2bd4 100644 --- a/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature +++ b/cucumber/authenticators_jwt/features/authn_jwt_token_schema.feature @@ -875,32 +875,32 @@ Feature: JWT Authenticator - Token Schema - !variable conjur/authn-jwt/raw/enforced-claims - !host - id: myapp + id: myapp-01 annotations: authn-jwt/raw/conjur.org/enforced-property: valid - !grant role: !group conjur/authn-jwt/raw/hosts - member: !host myapp + member: !host myapp-01 """ And I successfully set authn-jwt "enforced-claims" variable to value "conjur.org/enforced-property" And I successfully set authn-jwt "token-app-property" variable to value "conjur.org/host-property" And I add the secret value "test-secret" to the resource "cucumber:variable:test-variable" - And I permit host "myapp" to "execute" it + And I permit host "myapp-01" to "execute" it And I am using file "authn-jwt-token-schema" and alg "RS256" for remotely issue token: """ { "conjur.org/enforced-property":"valid", - "conjur.org/host-property":"myapp" + "conjur.org/host-property":"myapp-01" } """ And I save my place in the log file When I authenticate via authn-jwt with the JWT token - Then host "myapp" has been authorized by Conjur + Then host "myapp-01" has been authorized by Conjur And I successfully GET "/secrets/cucumber/variable/test-variable" with authorized user And The following appears in the log after my savepoint: """ - cucumber:host:myapp successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/raw + cucumber:host:myapp-01 successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/raw """ @sanity diff --git a/cucumber/authenticators_k8s/features/support/env.rb b/cucumber/authenticators_k8s/features/support/env.rb index ee654726b9..4bcebd1693 100644 --- a/cucumber/authenticators_k8s/features/support/env.rb +++ b/cucumber/authenticators_k8s/features/support/env.rb @@ -2,6 +2,17 @@ require 'rack/test' require 'json_spec/cucumber' +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://nginx#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@postgres#{ENV['TEST_ENV_NUMBER']}:5432/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + def app Rails.application end diff --git a/cucumber/authenticators_k8s/features/support/hooks.rb b/cucumber/authenticators_k8s/features/support/hooks.rb index c4fa9b56bd..b8df4fbcda 100644 --- a/cucumber/authenticators_k8s/features/support/hooks.rb +++ b/cucumber/authenticators_k8s/features/support/hooks.rb @@ -7,6 +7,15 @@ end Before do + parallel_cuke_vars = {} + parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "https://nginx#{ENV['TEST_ENV_NUMBER']}" + parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@postgres#{ENV['TEST_ENV_NUMBER']}:5432/postgres" + parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + + parallel_cuke_vars.each do |key, value| + ENV[key] = value + end + # Erase the certificate and cert injection logs from each container. kube_client.get_pods(namespace: namespace).select{|p| p.metadata.namespace == namespace}.each do |pod| next unless (ready_status = pod.status.conditions.find { |c| c.type == "Ready" }) diff --git a/cucumber/policy/features/support/client.rb b/cucumber/policy/features/support/client.rb index 3f4af64e13..c8e0b76d80 100644 --- a/cucumber/policy/features/support/client.rb +++ b/cucumber/policy/features/support/client.rb @@ -13,7 +13,7 @@ class Client ADMIN_PASSWORD = 'SEcret12!!!!' ACCOUNT = ENV['CONJUR_ACCOUNT'] || 'cucumber' - APPLIANCE_URL = ENV['CONJUR_APPLIANCE_URL'] || 'http://conjur' + APPLIANCE_URL = ENV['CONJUR_APPLIANCE_URL'] || "http://conjur#{ENV['TEST_ENV_NUMBER']}" class User def initialize(user_type, id) diff --git a/cucumber/policy/features/support/env.rb b/cucumber/policy/features/support/env.rb index 0a9bf2c17d..179752d970 100644 --- a/cucumber/policy/features/support/env.rb +++ b/cucumber/policy/features/support/env.rb @@ -5,7 +5,18 @@ require 'conjur-api' require 'rest-client' -Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || 'http://conjur' +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + +Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || "http://conjur#{ENV['TEST_ENV_NUMBER']}" Conjur.configuration.account = ENV['CONJUR_ACCOUNT'] || 'cucumber' # This is needed to run the cucumber --profile policy successfully diff --git a/cucumber/policy/features/support/hooks.rb b/cucumber/policy/features/support/hooks.rb index e8742d5d59..2f61a26020 100644 --- a/cucumber/policy/features/support/hooks.rb +++ b/cucumber/policy/features/support/hooks.rb @@ -18,6 +18,15 @@ # Prior to this hook, our tests had hidden coupling. This ensures each test is # run independently. Before do + parallel_cuke_vars = {} + parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" + parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" + parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + + parallel_cuke_vars.each do |key, value| + ENV[key] = value + end + @user_index = 0 Role.truncate(cascade: true) diff --git a/cucumber/rotators/features/step_definitions/rotator_steps.rb b/cucumber/rotators/features/step_definitions/rotator_steps.rb index 18ce8c7089..576e9ff89d 100644 --- a/cucumber/rotators/features/step_definitions/rotator_steps.rb +++ b/cucumber/rotators/features/step_definitions/rotator_steps.rb @@ -69,6 +69,9 @@ end Given(/^I add the value "(.*)" to variable "(.+)"$/) do |val, id| + if val == "testdb" + val = "#{val}#{ENV['TEST_ENV_NUMBER']}" + end @client.add_secret(id: id, value: val) end diff --git a/cucumber/rotators/features/support/env.rb b/cucumber/rotators/features/support/env.rb index 2cdb385df7..74ec8c5016 100644 --- a/cucumber/rotators/features/support/env.rb +++ b/cucumber/rotators/features/support/env.rb @@ -1,5 +1,16 @@ # frozen_string_literal: true +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + # so that we can require relative to the project root $LOAD_PATH.unshift(Dir.pwd) require 'config/environment' @@ -7,5 +18,5 @@ ENV['RAILS_ENV'] ||= 'test' ENV['CONJUR_LOG_LEVEL'] ||= 'debug' -Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || 'http://conjur' +Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || "http://conjur#{ENV['TEST_ENV_NUMBER']}" Conjur.configuration.account = ENV['CONJUR_ACCOUNT'] || 'cucumber' diff --git a/cucumber/rotators/features/support/rotator_helpers.rb b/cucumber/rotators/features/support/rotator_helpers.rb index 832961acca..184cb7b67c 100644 --- a/cucumber/rotators/features/support/rotator_helpers.rb +++ b/cucumber/rotators/features/support/rotator_helpers.rb @@ -11,7 +11,7 @@ module RotatorHelpers # Utility for the postgres rotator def run_sql_in_testdb(sql, user="postgres", pw="postgres_secret") - system("PGPASSWORD=#{pw} psql -h testdb -U #{user} -c \"#{sql}\"") + system("PGPASSWORD=#{pw} psql -h testdb#{ENV['TEST_ENV_NUMBER']} -U #{user} -c \"#{sql}\"") end def variable(id) @@ -75,7 +75,7 @@ def current_value # is hardcoded here. This shouldn't be problematic as there's likely no # need to make it dynamic. def pg_login_result(user, pw) - system("PGPASSWORD=#{pw} psql -c \"\\q\" -h testdb -U #{user}") + system("PGPASSWORD=#{pw} psql -c \"\\q\" -h testdb#{ENV['TEST_ENV_NUMBER']} -U #{user}") end end diff --git a/engines/conjur_audit/config/routes.rb b/engines/conjur_audit/config/routes.rb index 76ba647776..70e6a08710 100644 --- a/engines/conjur_audit/config/routes.rb +++ b/engines/conjur_audit/config/routes.rb @@ -1,5 +1,16 @@ # frozen_string_literal: true +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + ConjurAudit::Engine.routes.draw do scope format: false do root 'messages#index' diff --git a/engines/conjur_audit/spec/dummy/config/environments/test.rb b/engines/conjur_audit/spec/dummy/config/environments/test.rb index 08941f0fff..d94bba7023 100644 --- a/engines/conjur_audit/spec/dummy/config/environments/test.rb +++ b/engines/conjur_audit/spec/dummy/config/environments/test.rb @@ -1,5 +1,16 @@ # frozen_string_literal: true +parallel_cuke_vars = {} +parallel_cuke_vars['CONJUR_APPLIANCE_URL'] = "http://conjur#{ENV['TEST_ENV_NUMBER']}" +parallel_cuke_vars['DATABASE_URL'] = "postgres://postgres@pg#{ENV['TEST_ENV_NUMBER']}/postgres" +parallel_cuke_vars['CONJUR_AUTHN_API_KEY'] = ENV["CONJUR_AUTHN_API_KEY#{ENV['TEST_ENV_NUMBER']}"] + +parallel_cuke_vars.each do |key, value| + if ENV[key].nil? || ENV[key].empty? + ENV[key] = value + end +end + Rails.application.configure do config.cache_classes = true config.eager_load = false From 326b1f433c110e4e18944bfcfb9dcb3702c612ca Mon Sep 17 00:00:00 2001 From: Glen Johnson Date: Thu, 8 Jun 2023 08:59:30 -0600 Subject: [PATCH 32/42] Push latest tag to Redhat on promote --- publish-images.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/publish-images.sh b/publish-images.sh index 69abfc7ee0..be59e77ed7 100755 --- a/publish-images.sh +++ b/publish-images.sh @@ -142,6 +142,9 @@ if [[ "${REDHAT}" = true ]]; then # scan image with preflight tool scan_redhat_image "${REDHAT_REMOTE_IMAGE}:${VERSION}" "${REDHAT_CERT_PID}" + + # push latest tag to RH + tag_and_push "latest" "${RH_LOCAL_IMAGE}" "${REDHAT_REMOTE_IMAGE}" else echo 'Failed to log in to quay.io' exit 1 From b934de2f3bd6f6e715ff657569d356a1ab9f1bac Mon Sep 17 00:00:00 2001 From: telday Date: Tue, 18 Apr 2023 14:03:19 -0600 Subject: [PATCH 33/42] Update test env to use postgres 15 --- ci/docker-compose.yml | 6 +++--- dev/docker-compose.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index 47754bafda..ead0fead90 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -1,7 +1,7 @@ version: "3" services: pg: - image: postgres:10.16 + image: postgres:15 environment: # To avoid the following error: # @@ -29,13 +29,13 @@ services: POSTGRES_HOST_AUTH_METHOD: trust audit: - image: postgres:10.16 + image: postgres:15 environment: # See description on `pg` service for use of POSTGRES_HOST_AUTH_METHOD POSTGRES_HOST_AUTH_METHOD: trust testdb: - image: postgres:10.16 + image: postgres:15 environment: # To avoid the following error: # diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 88ab8e3539..98ca9589d7 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -1,7 +1,7 @@ version: "3" services: pg: - image: postgres:10.16 + image: postgres:15 environment: # To avoid the following error: # @@ -20,13 +20,13 @@ services: audit: - image: postgres:10.16 + image: postgres:15 environment: # See description on `pg` service for use of POSTGRES_HOST_AUTH_METHOD POSTGRES_HOST_AUTH_METHOD: trust testdb: - image: postgres:10.16 + image: postgres:15 environment: POSTGRES_PASSWORD: postgres_secret From dd496c22acc3aacb133bad38a667cbd54458a7ec Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 9 Feb 2023 15:30:42 -0700 Subject: [PATCH 34/42] Second round of revisions --- .../templates/authenticators/authn_oidc.rb | 102 ++++++++++++++++++ .../factory/templates/connections/database.rb | 95 ++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 app/domain/factory/templates/authenticators/authn_oidc.rb create mode 100644 app/domain/factory/templates/connections/database.rb diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb new file mode 100644 index 0000000000..ec63f76811 --- /dev/null +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Authenticators + class AuthnOidc + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= service_id %> + body: + - !webservice + + - !variable provider-uri + - !variable client-id + - !variable client-secret + + # URI of Conjur instance + - !variable redirect_uri + + # Defines the JWT claim to use as the Conjur identifier + - !variable claim-mapping + + - !group authenticatable + annotations: + description: Group with permission to authenticate using this authenticator + + - !permit + role: !group authenticatable + privilege: [ read, authenticate ] + resource: !webservice + + - !webservice status + annotations: + description: Web service for checking authenticator status + + - !group + id: operators + annotations: + description: Group with permission to check the authenticator status + + - !permit + role: !group operators + privilege: read + resource: !webservice status + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + target_policy_namespace: "conjur/authn-oidc", + target_variable_namespace: "conjur/authn-oidc/<%= service_id %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Managed Policy Template", + "description": "Policy with an owner group", + "type": "object", + "properties": { + "service-id": { + "description": "Service ID of the Authenticator", + "type": "string" + }, + "variables": { + "type": "object", + "properties": { + "provider-uri": { + "description": "OIDC Provider endpoint", + "type": "string" + }, + "client-id": { + "description": "OIDC Client ID", + "type": "string" + }, + "client-secret": { + "description": "OIDC Client Secret", + "type": "string" + }, + "redirect-uri": { + "description": "Target URL to redirect to after successful authentication", + "type": "string" + }, + "claim-mapping": { + "description": "OIDC JWT claim mapping. This value must match to a Conjur Host ID.", + "type": "string" + }, + }, + "required": %w[provider-uri client-id client-secret claim-mapping] + } + }, + "required": %w[service-id] + } + }.to_json) + end + end + end + end + end +end diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb new file mode 100644 index 0000000000..81561da215 --- /dev/null +++ b/app/domain/factory/templates/connections/database.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require 'base64' + +module Factory + module Templates + module Connections + class Database + class << self + def policy_template + <<~TEMPLATE + - !policy + id: <%= id %> + annotations: + factory: connections/database + body: + - &variables + - !variable url + - !variable port + - !variable username + - !variable password + + - !group consumers + - !group administrators + + # consumers can read and execute + - !permit + resource: *variables + privileges: [ read, execute ] + role: !group consumers + + # administrators can update (and read and execute, via role grant) + - !permit + resource: *variables + privileges: [ update ] + role: !group administrators + + # administrators has role consumers + - !grant + member: !group administrators + role: !group consumers + TEMPLATE + end + + def data + Base64.encode64({ + policy: Base64.encode64(policy_template), + target_policy_namespace: "<%= branch %>", + target_variable_namespace: "<%= branch %>/<%= id %>", + schema: { + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Database Connection Template", + "description": "All information for connecting to a database", + "type": "object", + "properties": { + "id": { + "description": "Database Connection ID", + "type": "string" + }, + "branch": { + "description": "Policy branch to load this database connection into", + "type": "string" + }, + "variables": { + "type": "object", + "properties": { + "url": { + "description": "Database URL", + "type": "string" + }, + "port": { + "description": "Database Port", + "type": "integer" + }, + "username": { + "description": "Database Username", + "type": "string" + }, + "password": { + "description": "Database Password", + "type": "string" + }, + }, + "required": %w[url port username password] + } + }, + "required": %w[id branch variables] + } + }.to_json) + end + end + end + end + end +end From 4c31f396d0605cfe848acaee5b068239994022d7 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 10 Feb 2023 15:47:31 -0700 Subject: [PATCH 35/42] small fixes, including - updates to policy - filter empty request params --- .../factory/templates/authenticators/authn_oidc.rb | 14 ++++++++------ .../factory/templates/connections/database.rb | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/domain/factory/templates/authenticators/authn_oidc.rb b/app/domain/factory/templates/authenticators/authn_oidc.rb index ec63f76811..ca5cd15241 100644 --- a/app/domain/factory/templates/authenticators/authn_oidc.rb +++ b/app/domain/factory/templates/authenticators/authn_oidc.rb @@ -19,12 +19,13 @@ def policy_template - !variable client-secret # URI of Conjur instance - - !variable redirect_uri + - !variable redirect-uri # Defines the JWT claim to use as the Conjur identifier - !variable claim-mapping - - !group authenticatable + - !group + id: authenticatable annotations: description: Group with permission to authenticate using this authenticator @@ -33,7 +34,8 @@ def policy_template privilege: [ read, authenticate ] resource: !webservice - - !webservice status + - !webservice + id: status annotations: description: Web service for checking authenticator status @@ -44,7 +46,7 @@ def policy_template - !permit role: !group operators - privilege: read + privilege: [ read ] resource: !webservice status TEMPLATE end @@ -56,8 +58,8 @@ def data target_variable_namespace: "conjur/authn-oidc/<%= service_id %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Managed Policy Template", - "description": "Policy with an owner group", + "title": "Authn-OIDC Template", + "description": "Create a new Authn-OIDC Authenticator", "type": "object", "properties": { "service-id": { diff --git a/app/domain/factory/templates/connections/database.rb b/app/domain/factory/templates/connections/database.rb index 81561da215..576c851eb6 100644 --- a/app/domain/factory/templates/connections/database.rb +++ b/app/domain/factory/templates/connections/database.rb @@ -70,7 +70,7 @@ def data }, "port": { "description": "Database Port", - "type": "integer" + "type": "string" }, "username": { "description": "Database Username", From e3ce9916e232ea5b21b7800708bf27d9ab2c4707 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Mon, 24 Apr 2023 12:28:58 -0600 Subject: [PATCH 36/42] Latest changes --- .../policy_factories_controller.rb | 35 +++++++++++++------ .../factories/create_from_policy_factory.rb | 13 +++++-- app/domain/factories/renderer.rb | 9 +++-- .../templates/base/v1/base_policy.rb | 1 + .../workflow-beta-activity.puml | 11 ------ lib/tasks/policy_factory.rake | 20 ++++++----- .../create_from_policy_factory_spec.rb | 0 .../domain/{factory => factories}/shared.rb | 0 .../authenticators/authn_oidc_spec.rb | 0 9 files changed, 53 insertions(+), 36 deletions(-) rename spec/app/domain/{factory => factories}/create_from_policy_factory_spec.rb (100%) rename spec/app/domain/{factory => factories}/shared.rb (100%) rename spec/app/domain/{factory => factories}/templates/authenticators/authn_oidc_spec.rb (100%) diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index 214fb6205e..17d263bfe0 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -8,17 +8,20 @@ class PolicyFactoriesController < RestController before_action :current_user def create - response = DB::Repository::PolicyFactoryRepository.new.find( - role: current_user, - **relevant_params(%i[account kind version id]) - ).bind do |factory| - Factories::CreateFromPolicyFactory.new.call( - account: params[:account], - factory_template: factory, - request_body: request.body.read, - authorization: request.headers["Authorization"] - ) - end + response = request_body_to_json(request.body.read) + .bind do |request_args| + DB::Repository::PolicyFactoryRepository.new.find( + role: current_user, + **relevant_params(%i[account kind version id]) + ).bind do |factory| + Factories::CreateFromPolicyFactory.new.call( + account: params[:account], + factory_template: factory, + request_body: request_args, + authorization: request.headers["Authorization"] + ) + end + end render_response(response) do render(json: response.result) @@ -74,4 +77,14 @@ def render_response(response, &block) def relevant_params(allowed_params) params.permit(*allowed_params).slice(*allowed_params).to_h.symbolize_keys end + + def request_body_to_json(request_body) + return ::FailureResponse.new("Request body must be JSON", status: :bad_request) if request_body.blank? + + begin + ::SuccessResponse.new(JSON.parse(request_body)) + rescue + ::FailureResponse.new("Request body must be valid JSON", status: :bad_request) + end + end end diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb index 4529999454..8ba3841f1f 100644 --- a/app/domain/factories/create_from_policy_factory.rb +++ b/app/domain/factories/create_from_policy_factory.rb @@ -5,11 +5,17 @@ require 'factories/renderer' module Factories + class Utilities + def self.filter_input(str) + str.gsub(/[^0-9a-z\-_]/i, '') + end + end class CreateFromPolicyFactory - def initialize(renderer: Factories::Renderer.new, http: RestClient, schema_validator: JSONSchemer) + def initialize(renderer: Factories::Renderer.new, http: RestClient, schema_validator: JSONSchemer, utilities: Factories::Utilities) @renderer = renderer @http = http @schema_validator = schema_validator + @utilities = utilities # JSON, URI, and Base64 are defined here for visibility. They # are not currently mocked in testing, thus, we're not setting @@ -29,7 +35,10 @@ def call(factory_template:, request_body:, account:, authorization:) ).bind do |body_variables| # Convert `dashed` keys to `underscored`. This only occurs for top-level parameters. # Conjur variables should be use dashes rather than underscores. - template_variables = body_variables.transform_keys { |key| key.to_s.underscore } + # Filter non-alpha-numeric, dash or underscore characters from inputs values (to prevent injection attacks). + template_variables = body_variables + .transform_keys { |key| key.to_s.underscore } + .transform_values { |value| @utilities.filter_input(value.to_s) } # Push rendered policy to the desired policy branch @renderer.render(template: factory_template.policy_namespace, variables: template_variables) diff --git a/app/domain/factories/renderer.rb b/app/domain/factories/renderer.rb index b7ac22765f..4ad14be495 100644 --- a/app/domain/factories/renderer.rb +++ b/app/domain/factories/renderer.rb @@ -1,12 +1,15 @@ +require 'responses' + module Factories class Renderer - def initialize(render_engine: ERB, success: SuccessResponse, failure: FailureResponse) + def initialize(render_engine: ERB) @render_engine = render_engine - @success = success - @failure = failure + @success = ::SuccessResponse + @failure = ::FailureResponse end def render(template:, variables:) + binding.pry @success.new(@render_engine.new(template, nil, '-').result_with_hash(variables)) rescue StandardError => e # Need to add tests to understand what exceptions are thrown when diff --git a/app/domain/factories/templates/base/v1/base_policy.rb b/app/domain/factories/templates/base/v1/base_policy.rb index 81a9749a78..71addadfc0 100644 --- a/app/domain/factories/templates/base/v1/base_policy.rb +++ b/app/domain/factories/templates/base/v1/base_policy.rb @@ -42,3 +42,4 @@ def policy end end end +end diff --git a/design/proposals/policy-factories/workflow-beta-activity.puml b/design/proposals/policy-factories/workflow-beta-activity.puml index 1dbbc38c12..baac746f20 100644 --- a/design/proposals/policy-factories/workflow-beta-activity.puml +++ b/design/proposals/policy-factories/workflow-beta-activity.puml @@ -15,17 +15,6 @@ if "Does factory variable exist?" then --> [yes] if "Factory has variables?" --> [yes] if "Variables set successfully set?" --> "Return Policy and Variable response" - note left - Response Code: 200 - Response: {"response": { - "code": 200, - "created_resources": [ - "::", - {":host:": {"api_key": ""}}, - ":variable:" - ] - }} - end note --> (*) else --> [no] "[Error] Setting Variable(s) not Permitted" diff --git a/lib/tasks/policy_factory.rake b/lib/tasks/policy_factory.rake index b3079ac81b..2f726cb7d2 100644 --- a/lib/tasks/policy_factory.rake +++ b/lib/tasks/policy_factory.rake @@ -37,18 +37,20 @@ namespace :policy_factory do end task test: :environment do - tester = Factories::Templates::ValidateTemplate.new - tester.test( - factory: Factories::Templates::Core::Group, - template_params: { "id"=>"test-group", "branch"=>"root", "annotations"=>{ "one"=>1, "two"=>2, "test/three"=>3 } } - ) - tester.test( - factory: Factories::Templates::Core::Group, - template_params: { "id"=>"test-group", "branch"=>"root" } - ) + binding.pry + # tester = Factories::Templates::ValidateTemplate.new + # tester.test( + # factory: Factories::Templates::Core::Group, + # template_params: { "id"=>"test-group", "branch"=>"root", "annotations"=>{ "one"=>1, "two"=>2, "test/three"=>3 } } + # ) + # tester.test( + # factory: Factories::Templates::Core::Group, + # template_params: { "id"=>"test-group", "branch"=>"root" } + # ) end task load: :environment do + binding.pry client.load_policy('root', Factories::Templates::Base::V1::BasePolicy.policy) client.resource('cucumber:variable:conjur/factories/core/v1/group').add_value(Factories::Templates::Core::V1::Group.data) client.resource('cucumber:variable:conjur/factories/core/v1/managed-policy').add_value(Factories::Templates::Core::V1::ManagedPolicy.data) diff --git a/spec/app/domain/factory/create_from_policy_factory_spec.rb b/spec/app/domain/factories/create_from_policy_factory_spec.rb similarity index 100% rename from spec/app/domain/factory/create_from_policy_factory_spec.rb rename to spec/app/domain/factories/create_from_policy_factory_spec.rb diff --git a/spec/app/domain/factory/shared.rb b/spec/app/domain/factories/shared.rb similarity index 100% rename from spec/app/domain/factory/shared.rb rename to spec/app/domain/factories/shared.rb diff --git a/spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb b/spec/app/domain/factories/templates/authenticators/authn_oidc_spec.rb similarity index 100% rename from spec/app/domain/factory/templates/authenticators/authn_oidc_spec.rb rename to spec/app/domain/factories/templates/authenticators/authn_oidc_spec.rb From 51dbe41cba9c11c916e819d5c1fa1e7c72f2fefa Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 23 Jun 2023 13:11:54 -0600 Subject: [PATCH 37/42] Updates to factory functionality --- .../policy_factories_controller.rb | 55 ++++++------------- .../repository/policy_factory_repository.rb | 13 +++-- .../factories/create_from_policy_factory.rb | 16 ++++-- app/domain/factories/renderer.rb | 3 +- app/domain/responses.rb | 3 +- app/presenters/policy_factory/index.rb | 22 ++++++++ app/presenters/policy_factory/show.rb | 20 +++++++ config/environments/development.rb | 2 +- 8 files changed, 82 insertions(+), 52 deletions(-) create mode 100644 app/presenters/policy_factory/index.rb create mode 100644 app/presenters/policy_factory/show.rb diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index 17d263bfe0..1aad12da41 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -8,20 +8,17 @@ class PolicyFactoriesController < RestController before_action :current_user def create - response = request_body_to_json(request.body.read) - .bind do |request_args| - DB::Repository::PolicyFactoryRepository.new.find( - role: current_user, - **relevant_params(%i[account kind version id]) - ).bind do |factory| - Factories::CreateFromPolicyFactory.new.call( - account: params[:account], - factory_template: factory, - request_body: request_args, - authorization: request.headers["Authorization"] - ) - end - end + response = DB::Repository::PolicyFactoryRepository.new.find( + role: current_user, + **relevant_params(%i[account kind version id]) + ).bind do |factory| + Factories::CreateFromPolicyFactory.new.call( + account: params[:account], + factory_template: factory, + request_body: request.body.read, + authorization: request.headers["Authorization"] + ) + end render_response(response) do render(json: response.result) @@ -36,7 +33,8 @@ def show ) render_response(response) do - render(json: response.result.schema) + presenter = Presenter::PolicyFactory::Show.new(factory: response.result) + render(json: presenter.present) end end @@ -46,16 +44,8 @@ def index account: params[:account] ) render_response(response) do - response_body = response.result.map do |factory| - { - name: factory.name, - namespace: factory.classification, - 'full-name': "#{factory.classification}/#{factory.name}", - 'current-version': factory.version, - description: factory.description || '' - } - end - render(json: response_body) + presenter = Presenter::PolicyFactory::Index.new(factories: response.result) + render(json: presenter.present) end end @@ -66,9 +56,10 @@ def render_response(response, &block) block.call else render( - json: response.message.merge( + json: { + message: response.message, code: HTTP::Response::Status::SYMBOL_CODES[response.status] - ), + }, status: response.status ) end @@ -77,14 +68,4 @@ def render_response(response, &block) def relevant_params(allowed_params) params.permit(*allowed_params).slice(*allowed_params).to_h.symbolize_keys end - - def request_body_to_json(request_body) - return ::FailureResponse.new("Request body must be JSON", status: :bad_request) if request_body.blank? - - begin - ::SuccessResponse.new(JSON.parse(request_body)) - rescue - ::FailureResponse.new("Request body must be valid JSON", status: :bad_request) - end - end end diff --git a/app/db/repository/policy_factory_repository.rb b/app/db/repository/policy_factory_repository.rb index bbb6a9646a..3babddc44a 100644 --- a/app/db/repository/policy_factory_repository.rb +++ b/app/db/repository/policy_factory_repository.rb @@ -11,7 +11,7 @@ module DataObjects :classification, :version, :policy, - :policy_namespace, + :policy_branch, :schema, :description, keyword_init: true @@ -43,8 +43,9 @@ def find_all(account:, role:) _, _, classification, _, factory = item.resource_id.split('/') [classification, factory].join('/') end - .map do |_, versions| - versions.max + .map do |unused, versions| + # find the most recent version + versions.max { |a, b| a.id <=> b.id } end .map do |factory| response = secret_to_data_object(factory) @@ -54,7 +55,7 @@ def find_all(account:, role:) if factories.empty? return @failure.new( - { message: 'Role does not have permission to use Factories' }, + 'Role does not have permission to use Factories', status: :forbidden ) end @@ -71,7 +72,7 @@ def find(kind:, id:, account:, role:, version: nil) :resource_id, "#{account}:variable:conjur/factories/#{kind}/%" ) - ).all.select { |i| i.resource_id.split('/').last == id }.max + ).all.select { |i| i.resource_id.split('/').last == id }.max { |a, b| a.id <=> b.id } end if factory.present? && role.allowed_to?(:execute, factory) @@ -103,7 +104,7 @@ def secret_to_data_object(variable) @success.new( @data_object.new( policy: Base64.decode64(decoded_factory['policy']), - policy_namespace: decoded_factory['policy_namespace'], + policy_branch: decoded_factory['policy_branch'], schema: decoded_factory['schema'], version: version, name: id, diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb index 8ba3841f1f..468b6e6b13 100644 --- a/app/domain/factories/create_from_policy_factory.rb +++ b/app/domain/factories/create_from_policy_factory.rb @@ -38,10 +38,16 @@ def call(factory_template:, request_body:, account:, authorization:) # Filter non-alpha-numeric, dash or underscore characters from inputs values (to prevent injection attacks). template_variables = body_variables .transform_keys { |key| key.to_s.underscore } - .transform_values { |value| @utilities.filter_input(value.to_s) } + .transform_values do |value| + if value.is_a?(Hash) + value.transform_values { |internal_value| @utilities.filter_input(internal_value.to_s) } + else + @utilities.filter_input(value.to_s) + end + end # Push rendered policy to the desired policy branch - @renderer.render(template: factory_template.policy_namespace, variables: template_variables) + @renderer.render(template: factory_template.policy_branch, variables: template_variables) .bind do |policy_load_path| valid_variables = factory_template.schema['properties'].keys - ['variables'] render_and_apply_policy( @@ -54,7 +60,7 @@ def call(factory_template:, request_body:, account:, authorization:) return @success.new(result) unless factory_template.schema['properties'].key?('variables') # Set Policy Factory variables - @renderer.render(template: "#{factory_template.policy_namespace}/<%= id %>", variables: template_variables) + @renderer.render(template: "#{factory_template.policy_branch}/<%= id %>", variables: template_variables) .bind do |variable_path| set_factory_variables( schema_variables: factory_template.schema['properties']['variables']['properties'], @@ -77,12 +83,12 @@ def call(factory_template:, request_body:, account:, authorization:) private def validate_and_transform_request(schema:, params:) - return @failure.new("Request body must be JSON", status: :bad_request) if params.blank? + return @failure.new('Request body must be JSON', status: :bad_request) if params.blank? begin params = @json.parse(params) rescue - return @failure.new("Request body must be valid JSON", status: :bad_request) + return @failure.new('Request body must be valid JSON', status: :bad_request) end # Strip keys without values diff --git a/app/domain/factories/renderer.rb b/app/domain/factories/renderer.rb index 4ad14be495..61f9653370 100644 --- a/app/domain/factories/renderer.rb +++ b/app/domain/factories/renderer.rb @@ -9,9 +9,8 @@ def initialize(render_engine: ERB) end def render(template:, variables:) - binding.pry @success.new(@render_engine.new(template, nil, '-').result_with_hash(variables)) - rescue StandardError => e + rescue => e # Need to add tests to understand what exceptions are thrown when # variables are missing. This may not be enough. @failure.new(e) diff --git a/app/domain/responses.rb b/app/domain/responses.rb index 05668e91c2..b1a96e1a46 100644 --- a/app/domain/responses.rb +++ b/app/domain/responses.rb @@ -30,7 +30,8 @@ class FailureResponse attr_reader :message, :status def initialize(message, level: :warn, status: :unauthorized) - @message = message + # If message comes in as a string, convert it to a hash + @message = message.is_a?(String) ? { message: message } : message @level = level @status = status end diff --git a/app/presenters/policy_factory/index.rb b/app/presenters/policy_factory/index.rb new file mode 100644 index 0000000000..cf57ad8532 --- /dev/null +++ b/app/presenters/policy_factory/index.rb @@ -0,0 +1,22 @@ +module Presenter + module PolicyFactory + # returns an array representation to be used by the controller + class Index + def initialize(factories:) + @factories = factories + end + + def present + @factories.map do |factory| + { + name: factory.name, + namespace: factory.classification, + 'full-name': "#{factory.classification}/#{factory.name}", + 'current-version': factory.version, + description: factory.description || '' + } + end + end + end + end +end diff --git a/app/presenters/policy_factory/show.rb b/app/presenters/policy_factory/show.rb new file mode 100644 index 0000000000..9e8f1184c3 --- /dev/null +++ b/app/presenters/policy_factory/show.rb @@ -0,0 +1,20 @@ +module Presenter + module PolicyFactory + # returns a hash representation to be used by the controller + class Show + def initialize(factory:) + @factory = factory + end + + def present + { + title: @factory.schema['title'], + version: @factory.version, + description: @factory.schema['description'], + properties: @factory.schema['properties'], + required: @factory.schema['required'] + } + end + end + end +end diff --git a/config/environments/development.rb b/config/environments/development.rb index d3b9a48acb..e6ba5ad073 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -15,7 +15,7 @@ # https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization # Accept multiple hosts for parallel tests - config.hosts << /^conjur[0-9]*$/ + config.hosts << /conjur[0-9]*/ # eager_load needed to make authentication work without the hacky # loading code... From eae44f5b8fccb93b2dad275453fe6f7e37eec547 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 29 Jun 2023 16:29:32 -0600 Subject: [PATCH 38/42] Improves error handling --- .../policy_factories_controller.rb | 5 +- .../repository/policy_factory_repository.rb | 2 +- .../factories/create_from_policy_factory.rb | 50 +++++++---- .../templates/authenticators/v1/authn_oidc.rb | 2 +- .../templates/base/v1/base_policy.rb | 14 ++- .../templates/connections/v1/database.rb | 2 +- app/domain/responses.rb | 88 +++++++++++-------- app/presenters/policy_factory/index.rb | 29 ++++-- 8 files changed, 118 insertions(+), 74 deletions(-) diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index 1aad12da41..0470edafbe 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -56,10 +56,7 @@ def render_response(response, &block) block.call else render( - json: { - message: response.message, - code: HTTP::Response::Status::SYMBOL_CODES[response.status] - }, + json: response.to_h, status: response.status ) end diff --git a/app/db/repository/policy_factory_repository.rb b/app/db/repository/policy_factory_repository.rb index 3babddc44a..d6160eff37 100644 --- a/app/db/repository/policy_factory_repository.rb +++ b/app/db/repository/policy_factory_repository.rb @@ -43,7 +43,7 @@ def find_all(account:, role:) _, _, classification, _, factory = item.resource_id.split('/') [classification, factory].join('/') end - .map do |unused, versions| + .map do |_, versions| # find the most recent version versions.max { |a, b| a.id <=> b.id } end diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb index 468b6e6b13..f03e286a41 100644 --- a/app/domain/factories/create_from_policy_factory.rb +++ b/app/domain/factories/create_from_policy_factory.rb @@ -80,7 +80,7 @@ def call(factory_template:, request_body:, account:, authorization:) end end - private + # private def validate_and_transform_request(schema:, params:) return @failure.new('Request body must be JSON', status: :bad_request) if params.blank? @@ -93,7 +93,6 @@ def validate_and_transform_request(schema:, params:) # Strip keys without values params = params.select{|_, v| v.present? } - validator = @schema_validator.schema(schema) return @success.new(params) if validator.valid?(params) @@ -103,7 +102,7 @@ def validate_and_transform_request(schema:, params:) missing_attributes = error['details']['missing_keys'].map{|key| [ error['data_pointer'], key].reject(&:empty?).join('/') } #.join("', '") missing_attributes.map do |attribute| { - message: "Missing JSON key or value for: '#{attribute}'", + message: "A value is required for '#{attribute}'", key: attribute } end @@ -121,30 +120,43 @@ def render_and_apply_policy(policy_load_path:, policy_template:, variables:, acc template: policy_template, variables: variables ).bind do |rendered_policy| - response = @http.post( - "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", - rendered_policy, - 'Authorization' => authorization - ) - if response.code == 201 - @success.new(response.body) - else - case response.code + begin + response = @http.post( + "http://localhost:3000/policies/#{account}/policy/#{policy_load_path}", + rendered_policy, + 'Authorization' => authorization + ) + rescue RestClient::ExceptionWithResponse => e + case e.response.code when 400 - @failure.new("Failed to apply generated Policy to '#{policy_load_path}'", status: :bad_request) + return @failure.new( + { message: "Failed to apply generated Policy to '#{policy_load_path}'", + request_error: e.response.body }, status: :bad_request + ) when 401 - @failure.new("Unauthorized to apply generated policy to '#{policy_load_path}'", status: :unauthorized) + return @failure.new( + { message: "Unauthorized to apply generated policy to '#{policy_load_path}'", + request_error: e.response.body }, status: :unauthorized + ) when 403 - @failure.new("Forbidden to apply generated policy to '#{policy_load_path}'", status: :forbidden) + return @failure.new( + { message: "Forbidden to apply generated policy to '#{policy_load_path}'", + request_error: e.response.body }, status: :forbidden + ) when 404 - @failure.new("Unable to apply generated policy to '#{policy_load_path}'", status: :not_found) + return @failure.new( + { message: "Unable to apply generated policy to '#{policy_load_path}'", + request_error: e.response.body }, status: :not_found + ) else - @failure.new( - "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", - status: :bad_request + return @failure.new( + { message: "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", + request_error: e.to_s }, status: :bad_request ) end end + + @success.new(response.body) end end diff --git a/app/domain/factories/templates/authenticators/v1/authn_oidc.rb b/app/domain/factories/templates/authenticators/v1/authn_oidc.rb index 8e27db3621..fbda6adf8e 100644 --- a/app/domain/factories/templates/authenticators/v1/authn_oidc.rb +++ b/app/domain/factories/templates/authenticators/v1/authn_oidc.rb @@ -58,7 +58,7 @@ def data Base64.encode64({ version: 'v1', policy: Base64.encode64(policy_template), - policy_namespace: "conjur/authn-oidc", + policy_branch: "conjur/authn-oidc", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Authn-OIDC Template", diff --git a/app/domain/factories/templates/base/v1/base_policy.rb b/app/domain/factories/templates/base/v1/base_policy.rb index 71addadfc0..5273cead4f 100644 --- a/app/domain/factories/templates/base/v1/base_policy.rb +++ b/app/domain/factories/templates/base/v1/base_policy.rb @@ -16,25 +16,35 @@ def policy body: - !policy id: core + annotations: + description: "Create Conjur primatives and manage permissions" body: - !variable id: v1/user annotations: description: Create a new User - - !variable v1/group - - !variable v1/policy - !variable v1/grant + - !variable v1/group + - !variable v1/host + - !variable v1/layer - !variable v1/managed-policy + - !variable v1/policy + - !variable v1/user - !policy id: authenticators + annotations: + description: "Generate new Authenticators" body: - !variable v1/authn-oidc - !policy id: connections + annotations: + description: "Create connections to external services" body: - !variable v1/database + - !variable v2/database TEMPLATE end end diff --git a/app/domain/factories/templates/connections/v1/database.rb b/app/domain/factories/templates/connections/v1/database.rb index 5e81c85a6d..68fb2442a8 100644 --- a/app/domain/factories/templates/connections/v1/database.rb +++ b/app/domain/factories/templates/connections/v1/database.rb @@ -47,7 +47,7 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Database Connection Template", diff --git a/app/domain/responses.rb b/app/domain/responses.rb index b1a96e1a46..26386aa780 100644 --- a/app/domain/responses.rb +++ b/app/domain/responses.rb @@ -3,51 +3,63 @@ # These response objects provide a mechanism for passing more complex response # information upstream -# module Utilities - # Responsible for handling "successful" requests. The - # response is returned via the `.result` method. - class SuccessResponse - attr_reader :result - - def initialize(result) - @result = result - end +# Responsible for handling "successful" requests. The +# response is returned via the `.result` method. +class SuccessResponse + attr_reader :result - def success? - true - end + def initialize(result) + @result = result + end - # The result of bind should always be another Response object, if the current - # response object is successful, #bind will call the next operation - def bind(&_block) - yield(result) - end + def success? + true end - # Responsible for handling "failed" requests. - # Log level and Response code are both option. - class FailureResponse - attr_reader :message, :status + # The result of bind should always be another Response object, if the current + # response object is successful, #bind will call the next operation + def bind(&_block) + yield(result) + end +end - def initialize(message, level: :warn, status: :unauthorized) - # If message comes in as a string, convert it to a hash - @message = message.is_a?(String) ? { message: message } : message - @level = level - @status = status - end +# Responsible for handling "failed" requests. +# Log level and Response code are both option. +class FailureResponse + attr_reader :message, :status - def success? - false - end + def initialize(message, level: :warn, status: :unauthorized) + @message = message + @level = level + @status = status + end - def level - @level.to_sym - end + def success? + false + end - # If the current response is a failure, further attempts to bind will just - # return this response again. - def bind - self + def level + @level.to_sym + end + + def to_h + { + code: HTTP::Response::Status::SYMBOL_CODES[@status] + }.tap do |rtn| + case @message + when Array + rtn[:errors] = @message + when Hash + rtn[:error] = @message + else + rtn[:error] = { message: @message.to_s } + end end end -# end + + # If the current response is a failure, further attempts to bind will just + # return this response again. + def bind + self + end +end diff --git a/app/presenters/policy_factory/index.rb b/app/presenters/policy_factory/index.rb index cf57ad8532..7942d1daf9 100644 --- a/app/presenters/policy_factory/index.rb +++ b/app/presenters/policy_factory/index.rb @@ -7,16 +7,29 @@ def initialize(factories:) end def present - @factories.map do |factory| - { - name: factory.name, - namespace: factory.classification, - 'full-name': "#{factory.classification}/#{factory.name}", - 'current-version': factory.version, - description: factory.description || '' - } + {}.tap do |rtn| + @factories + .group_by(&:classification) + .sort_by {|classification, _| classification } + .map do |classification, factories| + rtn[classification] = factories + .map { |factory| factory_to_hash(factory) } + .sort { |x, y| x[:name] <=> y[:name] } + end end end + + private + + def factory_to_hash(factory) + { + name: factory.name, + namespace: factory.classification, + 'full-name': "#{factory.classification}/#{factory.name}", + 'current-version': factory.version, + description: factory.description || '' + } + end end end end From 956e8f87d75c986a14b7c0f2dd0ee4ca176ee38f Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Wed, 5 Jul 2023 09:12:38 -0600 Subject: [PATCH 39/42] Test updates --- .../create_from_policy_factory_spec.rb | 90 ++++++++++++++++--- spec/app/domain/factories/shared.rb | 4 +- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/spec/app/domain/factories/create_from_policy_factory_spec.rb b/spec/app/domain/factories/create_from_policy_factory_spec.rb index ebf7e9e835..622cf2f399 100644 --- a/spec/app/domain/factories/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factories/create_from_policy_factory_spec.rb @@ -10,7 +10,7 @@ context 'with a simple factory' do let(:validated) do factory.validate_and_transform_request( - schema: JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['schema'], + schema: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['schema'], params: params ) end @@ -34,7 +34,7 @@ let(:params) { { id: 'foo' }.to_json } it 'returns a failure response' do expect(validated.success?).to be(false) - expect(validated.message).to eq([{ message: "Missing JSON key or value for: 'branch'", key: "branch" }]) + expect(validated.message).to eq([{ message: "A value is required for 'branch'", key: "branch" }]) expect(validated.status).to eq(:bad_request) end end @@ -42,7 +42,7 @@ let(:params) { { id: '', branch: 'foo' }.to_json } it 'returns a failure response' do expect(validated.success?).to be(false) - expect(validated.message).to eq([{ message: "Missing JSON key or value for: 'id'", key: 'id' }]) + expect(validated.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) expect(validated.status).to eq(:bad_request) end end @@ -63,18 +63,18 @@ it 'loads the approprate policy' do factory.render_and_apply_policy( policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['policy']), + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), variables: { 'id' => 'foo', 'branch' => 'bar' }, account: 'cucumber', authorization: 'bar' ) - expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) end end context 'when response is valid' do let(:args) do - ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}] + ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}] end let(:response) { double(RestClient::Response, code: 201, body: 'foo') } let(:rest_client) do @@ -86,7 +86,7 @@ it 'returns successfully' do response = factory.render_and_apply_policy( policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::User.data))['policy']), + policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), variables: { 'id' => 'foo', 'branch' => 'bar' }, account: 'cucumber', authorization: 'bar' @@ -217,14 +217,70 @@ describe('.call') do context 'when policy factory is only a policy' do + let(:policy_factory) do + decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) + policy_factory = DB::Repository::DataObjects::PolicyFactory.new( + policy: Base64.decode64(decoded_factory['policy']), + policy_branch: decoded_factory['policy_branch'], + schema: decoded_factory['schema'], + version: 'v1', + name: 'user', + classification: 'core', + description: '' + ) + end + it 'loads the appropriate policy' do factory.call( - factory_template: JSON.parse(Base64.decode64(Factories::Templates::Core::User.data)), + factory_template: policy_factory, request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json, account: 'cucumber', authorization: 'bar' ) - expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n ", {"Authorization"=>"bar"}) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) + end + + context 'when no JSON is present in request' do + it 'responds with the appropriate failure' do + response = factory.call( + factory_template: policy_factory, + request_body: nil, + account: 'cucumber', + authorization: 'bar' + ) + expect(response.success?).to eq(false) + expect(response.message).to eq('Request body must be JSON') + end + end + context 'when JSON keys are missing in request' do + it 'responds with the appropriate failure' do + response = factory.call( + factory_template: policy_factory, + request_body: {}.to_json, + account: 'cucumber', + authorization: 'bar' + ) + expect(response.success?).to eq(false) + expect(response.message).to eq([ + { key: 'id', message: "A value is required for 'id'" }, + { key: 'branch', message: "A value is required for 'branch'" } + ]) + end + end + context 'when JSON keys are missing values in the request' do + it 'responds with the appropriate failure' do + response = factory.call( + factory_template: policy_factory, + request_body: { id: '' }.to_json, + account: 'cucumber', + authorization: 'bar' + ) + expect(response.success?).to eq(false) + expect(response.message).to eq([ + { key: 'id', message: "A value is required for 'id'" }, + { key: 'branch', message: "A value is required for 'branch'" } + ]) + end end end @@ -232,7 +288,7 @@ let(:policy_load_args) do [ 'http://localhost:3000/policies/cucumber/policy/conjur/authn-oidc', - "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n - !variable redirect-uri\n - !variable claim-mapping\n\n - !group\n id: authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice\n id: status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: [ read ]\n resource: !webservice status\n", + "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n - !variable redirect-uri\n - !variable claim-mapping\n\n - !group\n id: authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice\n id: status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: [ read ]\n resource: !webservice status\n", { "Authorization"=>"bar" } ] end @@ -276,10 +332,20 @@ end end - let(:factory_template) { JSON.parse(Base64.decode64(Factories::Templates::Authenticators::AuthnOidc.data)) } + let(:factory_template) { JSON.parse(Base64.decode64(Factories::Templates::Authenticators::V1::AuthnOidc.data)) } it 'returns successfully' do + policy_factory = DB::Repository::DataObjects::PolicyFactory.new( + policy: Base64.decode64(factory_template['policy']), + policy_branch: factory_template['policy_branch'], + schema: factory_template['schema'], + version: 'v1', + name: 'authn-oidc', + classification: 'authenticators', + description: '' + ) + result = factory.call( - factory_template: factory_template, + factory_template: policy_factory, request_body: { 'id' => 'foo', 'variables' => { diff --git a/spec/app/domain/factories/shared.rb b/spec/app/domain/factories/shared.rb index aac46f7be3..58168d7ed2 100644 --- a/spec/app/domain/factories/shared.rb +++ b/spec/app/domain/factories/shared.rb @@ -5,9 +5,9 @@ let(:data) { JSON.parse(Base64.decode64(subject.data)) } let(:schema) { data['schema'] } - it 'includes policy, policy_namespace, and schema' do + it 'includes policy, policy_branch, and schema' do data_keys = data.keys.sort - expect(data_keys).to eq(%w[policy policy_namespace schema]) + expect(data_keys).to eq(%w[policy policy_branch schema]) end context 'JSON schema is valid' do From 43ed63b43742b99846af0da1af2ab3e8c12eede2 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Thu, 6 Jul 2023 11:19:19 -0600 Subject: [PATCH 40/42] Adds tests for presenters and repository --- Gemfile.lock | 4 - .../policy_factories_controller.rb | 4 +- .../repository/policy_factory_repository.rb | 19 +- .../factories/templates/core/v1/grant.rb | 12 +- .../factories/templates/core/v1/group.rb | 20 +- .../templates/core/v1/managed_policy.rb | 2 +- .../factories/templates/core/v1/policy.rb | 26 +- .../factories/templates/core/v1/user.rb | 28 +- .../index.rb | 4 +- .../show.rb | 2 +- .../policy_factory_repository_spec.rb | 388 ++++++++++++++++++ .../presenters/policy_factories/index_spec.rb | 47 +++ .../presenters/policy_factories/show_spec.rb | 60 +++ 13 files changed, 567 insertions(+), 49 deletions(-) rename app/presenters/{policy_factory => policy_factories}/index.rb (90%) rename app/presenters/{policy_factory => policy_factories}/show.rb (94%) create mode 100644 spec/app/db/repository/policy_factory_repository_spec.rb create mode 100644 spec/app/presenters/policy_factories/index_spec.rb create mode 100644 spec/app/presenters/policy_factories/show_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index 94dba54f9f..83557888c0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -472,11 +472,7 @@ GEM ffi (~> 1.1) table_print (1.5.7) thor (1.2.1) -<<<<<<< HEAD - timeout (0.3.1) -======= timeout (0.3.2) ->>>>>>> 70809583 (Update nokogiri & rails in Gemfile.lock, and nokogiri & commonmarker in docs/Gemfile.lock) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unf (0.1.4) diff --git a/app/controllers/policy_factories_controller.rb b/app/controllers/policy_factories_controller.rb index 0470edafbe..e67fb352f2 100644 --- a/app/controllers/policy_factories_controller.rb +++ b/app/controllers/policy_factories_controller.rb @@ -33,7 +33,7 @@ def show ) render_response(response) do - presenter = Presenter::PolicyFactory::Show.new(factory: response.result) + presenter = Presenter::PolicyFactories::Show.new(factory: response.result) render(json: presenter.present) end end @@ -44,7 +44,7 @@ def index account: params[:account] ) render_response(response) do - presenter = Presenter::PolicyFactory::Index.new(factories: response.result) + presenter = Presenter::PolicyFactories::Index.new(factories: response.result) render(json: presenter.present) end end diff --git a/app/db/repository/policy_factory_repository.rb b/app/db/repository/policy_factory_repository.rb index d6160eff37..fbde60cab0 100644 --- a/app/db/repository/policy_factory_repository.rb +++ b/app/db/repository/policy_factory_repository.rb @@ -38,6 +38,7 @@ def find_all(account:, role:) "#{account}:variable:conjur/factories/%" ) ).all + .select { |factory| role.allowed_to?(:execute, factory) } .group_by do |item| # form is: 'conjur/factories/core/v1/groups' _, _, classification, _, factory = item.resource_id.split('/') @@ -75,10 +76,6 @@ def find(kind:, id:, account:, role:, version: nil) ).all.select { |i| i.resource_id.split('/').last == id }.max { |a, b| a.id <=> b.id } end - if factory.present? && role.allowed_to?(:execute, factory) - return secret_to_data_object(factory) - end - resource_id = "#{kind}/#{version || 'v1'}/#{id}" if factory.blank? @@ -86,20 +83,22 @@ def find(kind:, id:, account:, role:, version: nil) { resource: resource_id, message: 'Requested Policy Factory does not exist' }, status: :not_found ) - elsif factory.secret.blank? + elsif !role.allowed_to?(:execute, factory) @failure.new( - { resource: resource_id, message: 'Requested Policy Factory is empty' }, - status: :bad_request + { resource: resource_id, message: 'Requested Policy Factory is not available' }, + status: :forbidden ) + else + secret_to_data_object(factory) end end private def secret_to_data_object(variable) + _, _, classification, version, id = variable.resource_id.split('/') factory = variable.secret&.value if factory - _, _, classification, version, id = variable.resource_id.split('/') decoded_factory = JSON.parse(Base64.decode64(factory)) @success.new( @data_object.new( @@ -109,13 +108,13 @@ def secret_to_data_object(variable) version: version, name: id, classification: classification, - description: variable.annotations.find { |a| a.name == 'description' }&.value + description: decoded_factory['schema']&.dig('description') ) ) else @failure.new( { resource: "#{classification}/#{version}/#{id}", message: 'Requested Policy Factory is not available' }, - status: :forbidden + status: :bad_request ) end end diff --git a/app/domain/factories/templates/core/v1/grant.rb b/app/domain/factories/templates/core/v1/grant.rb index 66a7076425..8deb053e86 100644 --- a/app/domain/factories/templates/core/v1/grant.rb +++ b/app/domain/factories/templates/core/v1/grant.rb @@ -20,17 +20,13 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Group Template", - "description": "Creates a Conjur Group", + "title": "Grant Template", + "description": "Assigns a Role to Role", "type": "object", "properties": { - "id": { - "description": "Group ID", - "type": "string" - }, "branch": { "description": "Policy branch to load this group into", "type": "string" @@ -40,7 +36,7 @@ def data "type": "object" } }, - "required": %w[id branch] + "required": %w[branch] } }.to_json) end diff --git a/app/domain/factories/templates/core/v1/group.rb b/app/domain/factories/templates/core/v1/group.rb index baa3bdbf6d..4d88549332 100644 --- a/app/domain/factories/templates/core/v1/group.rb +++ b/app/domain/factories/templates/core/v1/group.rb @@ -12,12 +12,14 @@ def policy_template <<~TEMPLATE - !group id: <%= id %> - <% if defined?(annotations) %> + <% if defined?(owner_role) && defined?(owner_type) -%> + owner: !<%= owner_type %> <%= owner_role %> + <% end -%> annotations: - <% annotations.each do |key, value| -%> + factory: core/v1/group + <% annotations.each do |key, value| -%> <%= key %>: <%= value %> - <% end -%> - <% end -%> + <% end -%> TEMPLATE end @@ -25,7 +27,7 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Group Template", @@ -40,6 +42,14 @@ def data "description": "Policy branch to load this group into", "type": "string" }, + "owner_role": { + "description": "The Conjur Role that will own this group", + "type": "string" + }, + "owner_type": { + "description": "The resource type of the owner of this group", + "type": "string" + }, "annotations": { "description": "Additional annotations to add to the group", "type": "object" diff --git a/app/domain/factories/templates/core/v1/managed_policy.rb b/app/domain/factories/templates/core/v1/managed_policy.rb index dcc1c45364..6c80123660 100644 --- a/app/domain/factories/templates/core/v1/managed_policy.rb +++ b/app/domain/factories/templates/core/v1/managed_policy.rb @@ -27,7 +27,7 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "Managed Policy Template", diff --git a/app/domain/factories/templates/core/v1/policy.rb b/app/domain/factories/templates/core/v1/policy.rb index e06dfefb85..0ac36a9578 100644 --- a/app/domain/factories/templates/core/v1/policy.rb +++ b/app/domain/factories/templates/core/v1/policy.rb @@ -12,15 +12,15 @@ def policy_template <<~TEMPLATE - !policy id: <%= id %> - <% if defined?(owner) %> - owner: <%= owner %> - <% end %> - <% if defined?(annotations) %> + <% if defined?(owner_role) && defined?(owner_type) -%> + owner: !<%= owner_type %> <%= owner_role %> + <% end -%> + <% if defined?(annotations) -%> annotations: - <% annotations.each do |key, value| -%> + <% annotations.each do |key, value| -%> <%= key %>: <%= value %> - <% end -%> - <% end -%> + <% end -%> + <% end -%> TEMPLATE end @@ -28,7 +28,7 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", @@ -43,12 +43,16 @@ def data "description": "Policy branch to load this policy into", "type": "string" }, - "owner": { - "description": "Optional owner of this policy", + "owner_role": { + "description": "The Conjur Role that will own this policy", + "type": "string" + }, + "owner_type": { + "description": "The resource type of the owner of this policy", "type": "string" }, "annotations": { - "description": "Additional annotations to add to the user", + "description": "Additional annotations to add to the policy", "type": "object" } }, diff --git a/app/domain/factories/templates/core/v1/user.rb b/app/domain/factories/templates/core/v1/user.rb index 907bbf5c86..1294590823 100644 --- a/app/domain/factories/templates/core/v1/user.rb +++ b/app/domain/factories/templates/core/v1/user.rb @@ -12,12 +12,18 @@ def policy_template <<~TEMPLATE - !user id: <%= id %> - <% if defined?(annotations) %> + <% if defined?(owner_role) && defined?(owner_type) -%> + owner: !<%= owner_type %> <%= owner_role %> + <% end -%> + <% if defined?(ip_range) -%> + restricted_to: <%= ip_range %> + <% end -%> + <% if defined?(annotations) -%> annotations: - <% annotations.each do |key, value| -%> + <% annotations.each do |key, value| -%> <%= key %>: <%= value %> - <% end -%> - <% end -%> + <% end -%> + <% end -%> TEMPLATE end @@ -25,7 +31,7 @@ def data Base64.encode64({ version: 1, policy: Base64.encode64(policy_template), - policy_namespace: "<%= branch %>", + policy_branch: "<%= branch %>", schema: { "$schema": "http://json-schema.org/draft-06/schema#", "title": "User Template", @@ -40,6 +46,18 @@ def data "description": "Policy branch to load this user into", "type": "string" }, + "owner_role": { + "description": "The Conjur Role that will own this user", + "type": "string" + }, + "owner_type": { + "description": "The resource type of the owner of this user", + "type": "string" + }, + "ip_range": { + "description": "Limits the network range the user is allowed to authenticate from", + "type": "string" + }, "annotations": { "description": "Additional annotations to add to the user", "type": "object" diff --git a/app/presenters/policy_factory/index.rb b/app/presenters/policy_factories/index.rb similarity index 90% rename from app/presenters/policy_factory/index.rb rename to app/presenters/policy_factories/index.rb index 7942d1daf9..36fea65755 100644 --- a/app/presenters/policy_factory/index.rb +++ b/app/presenters/policy_factories/index.rb @@ -1,6 +1,6 @@ module Presenter - module PolicyFactory - # returns an array representation to be used by the controller + module PolicyFactories + # returns a Hash representation to be used by the controller class Index def initialize(factories:) @factories = factories diff --git a/app/presenters/policy_factory/show.rb b/app/presenters/policy_factories/show.rb similarity index 94% rename from app/presenters/policy_factory/show.rb rename to app/presenters/policy_factories/show.rb index 9e8f1184c3..1bfdcd2f00 100644 --- a/app/presenters/policy_factory/show.rb +++ b/app/presenters/policy_factories/show.rb @@ -1,5 +1,5 @@ module Presenter - module PolicyFactory + module PolicyFactories # returns a hash representation to be used by the controller class Show def initialize(factory:) diff --git a/spec/app/db/repository/policy_factory_repository_spec.rb b/spec/app/db/repository/policy_factory_repository_spec.rb new file mode 100644 index 0000000000..081a4e1edb --- /dev/null +++ b/spec/app/db/repository/policy_factory_repository_spec.rb @@ -0,0 +1,388 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe(DB::Repository::PolicyFactoryRepository) do + subject { DB::Repository::PolicyFactoryRepository.new } + + describe 'find_all' do + context 'when no factories exist' do + before(:each) do + ::Role.create(role_id: 'rspec:group:conjur/policy-factory-users') + end + after(:each) do + ::Role['rspec:group:conjur/policy-factory-users'].destroy + end + it 'returns an error' do + response = subject.find_all( + account: 'foo-bar', + role: ::Role['rspec:group:conjur/policy-factory-users'] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:forbidden) + expect(response.message).to eq('Role does not have permission to use Factories') + end + end + + context 'when factories exist' do + let(:role_id) { 'rspec:group:conjur/policy-factory-users' } + let(:owner_id) { role_id } + let(:factory1) { 'rspec:variable:conjur/factories/core/v1/group' } + let(:factory2) { 'rspec:variable:conjur/factories/core/v1/user' } + + before(:each) do + ::Role.create(role_id: role_id) + end + after(:each) do + ::Role[role_id].destroy + end + + context 'when role does not have execute permission on any factories' do + let(:owner_id) { 'rspec:group:admin' } + before(:each) do + ::Role.create(role_id: owner_id) + ::Resource.create(resource_id: factory1, owner_id: owner_id) + ::Secret.create( + resource_id: factory1, + value: Factories::Templates::Core::V1::Group.data + ) + ::Resource.create(resource_id: factory2, owner_id: owner_id) + ::Secret.create( + resource_id: factory2, + value: Factories::Templates::Core::V1::User.data + ) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + ::Role[owner_id].destroy + end + it 'returns an error' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:forbidden) + expect(response.message).to eq('Role does not have permission to use Factories') + end + end + context 'when role has execute permission on some factories' do + let(:owner_id) { 'rspec:group:admin' } + before(:each) do + ::Role.create(role_id: owner_id) + ::Resource.create(resource_id: factory1, owner_id: role_id) + ::Secret.create( + resource_id: factory1, + value: Factories::Templates::Core::V1::Group.data + ) + ::Resource.create(resource_id: factory2, owner_id: owner_id) + ::Secret.create( + resource_id: factory2, + value: Factories::Templates::Core::V1::User.data + ) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + ::Role[owner_id].destroy + end + it 'returns permitted factories' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(true) + expect(response.result.count).to eq(1) + expect(response.result.first.name).to eq('group') + expect(response.result.first.description).to eq('Creates a Conjur Group') + end + end + context 'when role has execute permission on all factories' do + before(:each) do + ::Resource.create(resource_id: factory1, owner_id: role_id) + ::Secret.create( + resource_id: factory1, + value: Factories::Templates::Core::V1::Group.data + ) + ::Resource.create(resource_id: factory2, owner_id: role_id) + ::Secret.create( + resource_id: factory2, + value: Factories::Templates::Core::V1::User.data + ) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + end + it 'returns all factories' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + # binding.pry + expect(response.success?).to eq(true) + expect(response.result.count).to eq(2) + expect(response.result.map(&:name)).to include('group') + expect(response.result.map(&:name)).to include('user') + end + end + context 'when multiple versions of a factory exist' do + let(:factory1) { 'rspec:variable:conjur/factories/core/v1/group' } + let(:factory2) { 'rspec:variable:conjur/factories/core/v2/group' } + before(:each) do + ::Resource.create(resource_id: factory1, owner_id: role_id) + ::Secret.create( + resource_id: factory1, + value: Factories::Templates::Core::V1::Group.data + ) + ::Resource.create(resource_id: factory2, owner_id: role_id) + ::Secret.create( + resource_id: factory2, + value: Factories::Templates::Core::V1::Group.data + ) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + end + it 'returns the latest version' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(true) + expect(response.result.count).to eq(1) + expect(response.result.first.version).to eq('v2') + end + end + context 'when some factories are empty' do + before(:each) do + ::Resource.create(resource_id: factory1, owner_id: role_id) + ::Resource.create(resource_id: factory2, owner_id: role_id) + ::Secret.create( + resource_id: factory2, + value: Factories::Templates::Core::V1::User.data + ) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + end + it 'does not return empty factories' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(true) + expect(response.result.count).to eq(1) + expect(response.result.first.name).to eq('user') + end + end + context 'when all factories are empty' do + # TODO: this error is a bit weird... I'd expect a specific error if no factories were configured. + before(:each) do + ::Resource.create(resource_id: factory1, owner_id: role_id) + ::Resource.create(resource_id: factory2, owner_id: role_id) + end + after(:each) do + ::Resource[factory1].destroy + ::Resource[factory2].destroy + end + it 'does not return any factories' do + response = subject.find_all( + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:forbidden) + expect(response.message).to eq('Role does not have permission to use Factories') + end + end + end + end + + describe '.find' do + context 'when factory does not exist' do + before(:each) do + ::Role.create(role_id: 'rspec:group:conjur/policy-factory-users') + end + after(:each) do + ::Role['rspec:group:conjur/policy-factory-users'].destroy + end + it 'returns an error' do + response = subject.find( + kind: 'foo', + id: 'bar', + account: 'foo-bar', + role: ::Role['rspec:group:conjur/policy-factory-users'] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:not_found) + expect(response.message).to include( + { + resource: 'foo/v1/bar', + message: 'Requested Policy Factory does not exist' + } + ) + end + end + context 'when factory exists' do + context 'when requesting role does not have permission' do + let(:role_id) { 'rspec:group:conjur/policy-factory-users' } + let(:resource_id) { 'rspec:variable:conjur/factories/core/v1/group' } + before(:each) do + ::Role.create(role_id: role_id) + admin = ::Role.create(role_id: 'rspec:user:admin') + ::Resource.create(resource_id: resource_id, owner: admin) + end + after(:each) do + ::Role[role_id].destroy + ::Resource[resource_id].destroy + ::Role['rspec:user:admin'].destroy + end + it 'returns an error' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:forbidden) + expect(response.message).to include( + { + resource: 'core/v1/group', + message: 'Requested Policy Factory is not available' + } + ) + end + end + context 'when factory is empty' do + let(:role_id) { 'rspec:group:conjur/policy-factory-users' } + let(:resource_id) { 'rspec:variable:conjur/factories/core/v1/group' } + before(:each) do + ::Role.create(role_id: role_id) + ::Resource.create(resource_id: resource_id, owner_id: role_id) + end + after(:each) do + ::Resource[resource_id].destroy + ::Role[role_id].destroy + end + it 'returns an error' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(false) + expect(response.status).to eq(:bad_request) + expect(response.message).to include( + { + resource: 'core/v1/group', + message: 'Requested Policy Factory is not available' + } + ) + end + end + context 'requesting role has permission' do + let(:role_id) { 'rspec:group:conjur/policy-factory-users' } + let(:resource_id) { 'rspec:variable:conjur/factories/core/v1/group' } + before(:each) do + ::Role.create(role_id: role_id) + ::Resource.create(resource_id: resource_id, owner_id: role_id) + ::Secret.create( + resource_id: resource_id, + value: Factories::Templates::Core::V1::Group.data + ) + end + after(:each) do + ::Resource[resource_id].destroy + ::Role[role_id].destroy + end + it 'returns the policy factory' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(true) + expect(response.result.class).to eq(DB::Repository::DataObjects::PolicyFactory) + expect(response.result.name).to eq('group') + end + end + context 'when multiple versions exist' do + let(:owner_id) { 'rspec:group:conjur/policy-factory-users' } + let(:version1) { 'rspec:variable:conjur/factories/core/v1/group' } + let(:version2) { 'rspec:variable:conjur/factories/core/v2/group' } + before(:each) do + ::Role.create(role_id: owner_id) + ::Resource.create(resource_id: version1, owner_id: owner_id) + ::Secret.create( + resource_id: version1, + value: Factories::Templates::Core::V1::Group.data + ) + ::Resource.create(resource_id: version2, owner_id: owner_id) + ::Secret.create( + resource_id: version2, + value: Factories::Templates::Core::V1::Group.data + ) + end + after(:each) do + ::Resource[version1].destroy + ::Resource[version2].destroy + ::Role[owner_id].destroy + end + context 'when no version is provided' do + it 'returns the latest version' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[owner_id] + ) + expect(response.success?).to eq(true) + expect(response.result.version).to eq('v2') + end + end + context 'when a version is provided' do + it 'returns the requested version' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[owner_id], + version: 'v1' + ) + expect(response.success?).to eq(true) + expect(response.result.version).to eq('v1') + end + end + end + end + end + + # let(:factories) { %i[group user] } + # before(:each) do + # ::Role.create( + # role_id: 'rspec:group:conjur/policy-factory-users' + # ) + # factories.each do |factory| + + # # Webservice for authenticator + # ::Resource.create( + # resource_id: "rspec::variable:conjur/factories/core/v1/#{factory}", + # owner_id: 'rspec:group:conjur/policy-factory-users' + # ) + # # Webservice for authenticator status + # ::Resource.create( + # resource_id: "rspec:webservice:conjur/authn-oidc/#{service}/status", + # owner_id: 'rspec:group:conjur/policy-factory-users' + # ) + # end + # end + + +end diff --git a/spec/app/presenters/policy_factories/index_spec.rb b/spec/app/presenters/policy_factories/index_spec.rb new file mode 100644 index 0000000000..32e1e23d60 --- /dev/null +++ b/spec/app/presenters/policy_factories/index_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe(Presenter::PolicyFactories::Index) do + describe '.present' do + subject do + Presenter::PolicyFactories::Index.new( + factories: [ + DB::Repository::DataObjects::PolicyFactory.new( + name: 'foo1', + classification: 'foo', + version: 'v1', + description: 'This is foo' + ), + DB::Repository::DataObjects::PolicyFactory.new( + name: 'bar1', + classification: 'foo', + version: 'v1' + ) + ] + ) + end + + it 'returns the expected hash' do + expect(subject.present).to include( + { + "foo" => [ + { + name: 'bar1', + namespace: 'foo', + 'full-name': 'foo/bar1', + 'current-version': 'v1', + description: '' + }, { + name: 'foo1', + namespace: 'foo', + 'full-name': 'foo/foo1', + 'current-version': 'v1', + description: 'This is foo' + } + ] + } + ) + end + end +end diff --git a/spec/app/presenters/policy_factories/show_spec.rb b/spec/app/presenters/policy_factories/show_spec.rb new file mode 100644 index 0000000000..ca93784abe --- /dev/null +++ b/spec/app/presenters/policy_factories/show_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe(Presenter::PolicyFactories::Show) do + describe '.present' do + subject { Presenter::PolicyFactories::Show.new(factory: factory) } + context 'when factory is composed of string keys' do + let(:factory) do + DB::Repository::DataObjects::PolicyFactory.new( + schema: { + 'title' => 'foo-bar', + 'description' => 'some factory', + 'properties' => { + 'id' => { + 'description' => 'Group ID', + 'type' => 'string' + }, + 'branch' => { + 'description' => 'Policy branch to load this group into', + 'type' => 'string' + }, + 'annotations' => { + 'description' => 'Additional annotations to add to the group', + 'type' => 'object' + } + }, + 'required' => %w[id branch] + }, + version: 'v1' + ) + end + + it 'returns the expected hash' do + expect(subject.present).to include( + { + title: 'foo-bar', + version: 'v1', + description: 'some factory', + properties: { + 'annotations' => { + 'description' => 'Additional annotations to add to the group', + 'type' => 'object' + }, + 'branch' => { + 'description' => 'Policy branch to load this group into', + 'type' => 'string' + }, + 'id' => { + 'description' => 'Group ID', + 'type' => 'string' + } + }, + required: %w[id branch] + } + ) + end + end + end +end From cccf177a9a05ffc52d7f4dd766815019f3d9c41b Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 7 Jul 2023 15:44:52 -0600 Subject: [PATCH 41/42] More tests --- .../repository/policy_factory_repository.rb | 2 +- .../factories/create_from_policy_factory.rb | 16 +- app/domain/factories/renderer.rb | 4 + .../policy_factory_repository_spec.rb | 45 +- .../create_from_policy_factory_spec.rb | 591 ++++++++---------- spec/app/domain/factories/renderer_spec.rb | 98 +++ 6 files changed, 396 insertions(+), 360 deletions(-) create mode 100644 spec/app/domain/factories/renderer_spec.rb diff --git a/app/db/repository/policy_factory_repository.rb b/app/db/repository/policy_factory_repository.rb index fbde60cab0..0f0001a4a7 100644 --- a/app/db/repository/policy_factory_repository.rb +++ b/app/db/repository/policy_factory_repository.rb @@ -108,7 +108,7 @@ def secret_to_data_object(variable) version: version, name: id, classification: classification, - description: decoded_factory['schema']&.dig('description') + description: decoded_factory['schema']&.dig('description').to_s ) ) else diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb index f03e286a41..6f8292bf80 100644 --- a/app/domain/factories/create_from_policy_factory.rb +++ b/app/domain/factories/create_from_policy_factory.rb @@ -11,21 +11,21 @@ def self.filter_input(str) end end class CreateFromPolicyFactory + def initialize(renderer: Factories::Renderer.new, http: RestClient, schema_validator: JSONSchemer, utilities: Factories::Utilities) @renderer = renderer @http = http @schema_validator = schema_validator @utilities = utilities - # JSON, URI, and Base64 are defined here for visibility. They - # are not currently mocked in testing, thus, we're not setting - # them in the initializer. + # JSON and URI are defined here for visibility. They are not currently + # mocked in testing, thus, we're not setting them in the initializer. @json = JSON @uri = URI # Defined here for visibility. We shouldn't need to mock these. - @success = SuccessResponse - @failure = FailureResponse + @success = ::SuccessResponse + @failure = ::FailureResponse end def call(factory_template:, request_body:, account:, authorization:) @@ -70,17 +70,17 @@ def call(factory_template:, request_body:, account:, authorization:) account: account ) end - .bind { + .bind do # If variables were added successfully, return the result so that # we send the policy load response back to the client. @success.new(result) - } + end end end end end - # private + private def validate_and_transform_request(schema:, params:) return @failure.new('Request body must be JSON', status: :bad_request) if params.blank? diff --git a/app/domain/factories/renderer.rb b/app/domain/factories/renderer.rb index 61f9653370..6e77d6c8df 100644 --- a/app/domain/factories/renderer.rb +++ b/app/domain/factories/renderer.rb @@ -10,6 +10,10 @@ def initialize(render_engine: ERB) def render(template:, variables:) @success.new(@render_engine.new(template, nil, '-').result_with_hash(variables)) + + # If variable in template is missing from variable list + rescue NameError => e + @failure.new("Required template variable '#{e.name}' is missing") rescue => e # Need to add tests to understand what exceptions are thrown when # variables are missing. This may not be enough. diff --git a/spec/app/db/repository/policy_factory_repository_spec.rb b/spec/app/db/repository/policy_factory_repository_spec.rb index 081a4e1edb..45d9280267 100644 --- a/spec/app/db/repository/policy_factory_repository_spec.rb +++ b/spec/app/db/repository/policy_factory_repository_spec.rb @@ -312,6 +312,29 @@ expect(response.result.class).to eq(DB::Repository::DataObjects::PolicyFactory) expect(response.result.name).to eq('group') end + context 'when description attribute is missing' do + before(:each) do + data = Factories::Templates::Core::V1::Group.data + decoded_data = JSON.parse(Base64.decode64(data)) + decoded_data['schema'].delete('description') + + ::Secret.create( + resource_id: resource_id, + value: Base64.encode64(decoded_data.to_json) + ) + end + it 'includes an empty description' do + response = subject.find( + kind: 'core', + id: 'group', + account: 'rspec', + role: ::Role[role_id] + ) + expect(response.success?).to eq(true) + expect(response.result.description).to eq('') + end + + end end context 'when multiple versions exist' do let(:owner_id) { 'rspec:group:conjur/policy-factory-users' } @@ -363,26 +386,4 @@ end end end - - # let(:factories) { %i[group user] } - # before(:each) do - # ::Role.create( - # role_id: 'rspec:group:conjur/policy-factory-users' - # ) - # factories.each do |factory| - - # # Webservice for authenticator - # ::Resource.create( - # resource_id: "rspec::variable:conjur/factories/core/v1/#{factory}", - # owner_id: 'rspec:group:conjur/policy-factory-users' - # ) - # # Webservice for authenticator status - # ::Resource.create( - # resource_id: "rspec:webservice:conjur/authn-oidc/#{service}/status", - # owner_id: 'rspec:group:conjur/policy-factory-users' - # ) - # end - # end - - end diff --git a/spec/app/domain/factories/create_from_policy_factory_spec.rb b/spec/app/domain/factories/create_from_policy_factory_spec.rb index 622cf2f399..fdf1785510 100644 --- a/spec/app/domain/factories/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factories/create_from_policy_factory_spec.rb @@ -5,362 +5,295 @@ RSpec.describe(Factories::CreateFromPolicyFactory) do let(:rest_client) { spy(RestClient) } let(:factory) { Factories::CreateFromPolicyFactory.new(http: rest_client) } + # let(:simple_decoded_factory) { JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) } + let(:simple_factory) do + decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) + DB::Repository::DataObjects::PolicyFactory.new( + schema: decoded_factory['schema'], + policy: Base64.decode64(decoded_factory['policy']), + policy_branch: decoded_factory['policy_branch'] + ) + end - describe('.validate_and_transform_request') do - context 'with a simple factory' do - let(:validated) do - factory.validate_and_transform_request( - schema: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['schema'], - params: params - ) - end + describe('.call') do + let(:response) do + factory.call( + factory_template: simple_factory, + request_body: request, + account: 'rspec', + authorization: 'foo-bar' + ) + end + + context 'when request is invalid' do context 'when request body is missing' do - let(:params) { nil } + let(:request) { nil } it 'returns a failure response' do - expect(validated.success?).to be(false) - expect(validated.message).to eq("Request body must be JSON") - expect(validated.status).to eq(:bad_request) + expect(response.success?).to be(false) + expect(response.message).to eq('Request body must be JSON') + expect(response.status).to eq(:bad_request) + end + end + context 'when request body is empty' do + let(:request) { '' } + it 'returns a failure response' do + expect(response.success?).to be(false) + expect(response.message).to eq('Request body must be JSON') + expect(response.status).to eq(:bad_request) end end context 'when request body is malformed JSON' do - let(:params) { '{"foo": "bar }' } + let(:request) { '{"foo": "bar }' } it 'returns a failure response' do - expect(validated.success?).to be(false) - expect(validated.message).to eq("Request body must be valid JSON") - expect(validated.status).to eq(:bad_request) + expect(response.success?).to be(false) + expect(response.message).to eq('Request body must be valid JSON') + expect(response.status).to eq(:bad_request) end end context 'when request body is missing keys' do - let(:params) { { id: 'foo' }.to_json } + let(:request) { { id: 'foo' }.to_json } it 'returns a failure response' do - expect(validated.success?).to be(false) - expect(validated.message).to eq([{ message: "A value is required for 'branch'", key: "branch" }]) - expect(validated.status).to eq(:bad_request) + expect(response.success?).to be(false) + expect(response.message).to eq([{ message: "A value is required for 'branch'", key: 'branch' }]) + expect(response.status).to eq(:bad_request) end end context 'when request body is missing values' do - let(:params) { { id: '', branch: 'foo' }.to_json } + let(:request) { { id: '', branch: 'foo' }.to_json } it 'returns a failure response' do - expect(validated.success?).to be(false) - expect(validated.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) - expect(validated.status).to eq(:bad_request) + expect(response.success?).to be(false) + expect(response.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) + expect(response.status).to eq(:bad_request) end end context 'when request body is valid' do - let(:params) { { id: 'foo', branch: 'bar' }.to_json } - it 'returns a failure response' do - expect(validated.success?).to be(true) - validated.bind {|result| expect(result).to eq({ 'id' => 'foo', 'branch' => 'bar' }) } - end - end - end - end - - describe('.render_and_apply_policy') do - # Technically we should mock the Factories::Renderer to make this truely a unit - # test. I'm including it here to avoid needing to maintain an extra interface. - context 'The expected data is posted to the Conjur API' do - it 'loads the approprate policy' do - factory.render_and_apply_policy( - policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), - variables: { 'id' => 'foo', 'branch' => 'bar' }, - account: 'cucumber', - authorization: 'bar' - ) - expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) - end - end - - context 'when response is valid' do - let(:args) do - ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}] - end - let(:response) { double(RestClient::Response, code: 201, body: 'foo') } - let(:rest_client) do - class_double(RestClient).tap do |double| - allow(double).to receive(:post).with(*args).and_return(response) + let(:request) { { id: 'foo', branch: 'bar' }.to_json } + it 'submits the expected policy to Conjur' do + expect(response.success?).to be(true) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/rspec/policy/bar', "- !user\n id: foo\n", { 'Authorization' => 'foo-bar' }) end end - - it 'returns successfully' do - response = factory.render_and_apply_policy( - policy_load_path: 'bar', - policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), - variables: { 'id' => 'foo', 'branch' => 'bar' }, - account: 'cucumber', - authorization: 'bar' - ) - expect(response.success?).to be(true) - end end end - describe('.set_factory_variables') do - let(:rest_client) do - class_double(RestClient).tap do |double| - rest_client_requests.each do |request, value| - allow(double).to receive(:post).with(request, value, authorization).and_return(response) - end - end - end - let(:authorization) { { "Authorization"=>"baz" } } - let(:rest_client_requests) do - { - 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Ffoo' => 'bing', - 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Fbar' => 'bang' - } - end - context 'when role is unauthorized' do - let(:response) { double(RestClient::Response, code: 401) } - it 'returns a failure response' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '', 'bar' => '' }, - factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(false) - expect(response.status).to eq(:unauthorized) - expect(response.message).to eq( - "Role is unauthorized to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" - ) - end - end - context 'when role lacks privilege' do - let(:response) { double(RestClient::Response, code: 403) } - it 'returns a failure response' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '', 'bar' => '' }, - factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(false) - expect(response.status).to eq(:forbidden) - expect(response.message).to eq( - "Role lacks the privilege to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" - ) - end - end - context 'when variable is not present' do - let(:response) { double(RestClient::Response, code: 404, body: 'response') } - it 'returns a failure response' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '', 'bar' => '' }, - factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(false) - expect(response.status).to eq(:bad_request) - expect(response.message).to eq( - "Failed to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'. Status Code: '404', Response: 'response'" - ) - end - end - context 'when request is expected to be valid' do - let(:response) { double(RestClient::Response, code: 201) } - context 'when factory includes multiple variables' do - it 'is successful' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '', 'bar' => '' }, - factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(true) - end - context 'when factory includes a single variables' do - it 'is successful' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '' }, - factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(true) - end - end - context 'when factory includes a variable not present in request' do - it 'is successful' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '', 'bar' => '' }, - factory_variables: { 'foo' => 'bing' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(true) - end - end - context 'when request includes a value not present in the factory' do - it 'is successful' do - response = factory.set_factory_variables( - schema_variables: { 'foo' => '' }, - factory_variables: { 'foo' => 'bing', 'bing' => 'foo' }, - variable_path: 'foo/bar', - account: 'cucumber', - authorization: 'baz' - ) - expect(response.success?).to eq(true) - end - end - end - end - end - describe('.call') do - context 'when policy factory is only a policy' do - let(:policy_factory) do - decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) - policy_factory = DB::Repository::DataObjects::PolicyFactory.new( - policy: Base64.decode64(decoded_factory['policy']), - policy_branch: decoded_factory['policy_branch'], - schema: decoded_factory['schema'], - version: 'v1', - name: 'user', - classification: 'core', - description: '' - ) - end + # describe('.validate_and_transform_request') do + # context 'with a simple factory' do + # let(:validated) do + # factory.validate_and_transform_request( + # schema: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['schema'], + # params: params + # ) + # end + # context 'when request body is missing' do + # let(:params) { nil } + # it 'returns a failure response' do + # expect(validated.success?).to be(false) + # expect(validated.message).to eq("Request body must be JSON") + # expect(validated.status).to eq(:bad_request) + # end + # end + # context 'when request body is malformed JSON' do + # let(:params) { '{"foo": "bar }' } + # it 'returns a failure response' do + # expect(validated.success?).to be(false) + # expect(validated.message).to eq("Request body must be valid JSON") + # expect(validated.status).to eq(:bad_request) + # end + # end + # context 'when request body is missing keys' do + # let(:params) { { id: 'foo' }.to_json } + # it 'returns a failure response' do + # expect(validated.success?).to be(false) + # expect(validated.message).to eq([{ message: "A value is required for 'branch'", key: "branch" }]) + # expect(validated.status).to eq(:bad_request) + # end + # end + # context 'when request body is missing values' do + # let(:params) { { id: '', branch: 'foo' }.to_json } + # it 'returns a failure response' do + # expect(validated.success?).to be(false) + # expect(validated.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) + # expect(validated.status).to eq(:bad_request) + # end + # end + # context 'when request body is valid' do + # let(:params) { { id: 'foo', branch: 'bar' }.to_json } + # it 'returns a failure response' do + # expect(validated.success?).to be(true) + # validated.bind {|result| expect(result).to eq({ 'id' => 'foo', 'branch' => 'bar' }) } + # end + # end + # end + # end - it 'loads the appropriate policy' do - factory.call( - factory_template: policy_factory, - request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json, - account: 'cucumber', - authorization: 'bar' - ) - expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) - end + # describe('.render_and_apply_policy') do + # # Technically we should mock the Factories::Renderer to make this truely a unit + # # test. I'm including it here to avoid needing to maintain an extra interface. + # context 'The expected data is posted to the Conjur API' do + # it 'loads the approprate policy' do + # factory.render_and_apply_policy( + # policy_load_path: 'bar', + # policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), + # variables: { 'id' => 'foo', 'branch' => 'bar' }, + # account: 'cucumber', + # authorization: 'bar' + # ) + # expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) + # end + # end - context 'when no JSON is present in request' do - it 'responds with the appropriate failure' do - response = factory.call( - factory_template: policy_factory, - request_body: nil, - account: 'cucumber', - authorization: 'bar' - ) - expect(response.success?).to eq(false) - expect(response.message).to eq('Request body must be JSON') - end - end - context 'when JSON keys are missing in request' do - it 'responds with the appropriate failure' do - response = factory.call( - factory_template: policy_factory, - request_body: {}.to_json, - account: 'cucumber', - authorization: 'bar' - ) - expect(response.success?).to eq(false) - expect(response.message).to eq([ - { key: 'id', message: "A value is required for 'id'" }, - { key: 'branch', message: "A value is required for 'branch'" } - ]) - end - end - context 'when JSON keys are missing values in the request' do - it 'responds with the appropriate failure' do - response = factory.call( - factory_template: policy_factory, - request_body: { id: '' }.to_json, - account: 'cucumber', - authorization: 'bar' - ) - expect(response.success?).to eq(false) - expect(response.message).to eq([ - { key: 'id', message: "A value is required for 'id'" }, - { key: 'branch', message: "A value is required for 'branch'" } - ]) - end - end - end + # context 'when response is valid' do + # let(:args) do + # ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}] + # end + # let(:response) { double(RestClient::Response, code: 201, body: 'foo') } + # let(:rest_client) do + # class_double(RestClient).tap do |double| + # allow(double).to receive(:post).with(*args).and_return(response) + # end + # end - context 'when policy factory is policy and variables' do - let(:policy_load_args) do - [ - 'http://localhost:3000/policies/cucumber/policy/conjur/authn-oidc', - "- !policy\n id: foo\n body:\n - !webservice\n\n - !variable provider-uri\n - !variable client-id\n - !variable client-secret\n - !variable redirect-uri\n - !variable claim-mapping\n\n - !group\n id: authenticatable\n annotations:\n description: Group with permission to authenticate using this authenticator\n\n - !permit\n role: !group authenticatable\n privilege: [ read, authenticate ]\n resource: !webservice\n\n - !webservice\n id: status\n annotations:\n description: Web service for checking authenticator status\n\n - !group\n id: operators\n annotations:\n description: Group with permission to check the authenticator status\n\n - !permit\n role: !group operators\n privilege: [ read ]\n resource: !webservice status\n", - { "Authorization"=>"bar" } - ] - end - let(:provider_uri_args) do - [ - 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fprovider-uri', - 'foo', - { 'Authorization' => 'bar' } - ] - end - let(:client_id_args) do - [ - 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-id', - 'bar', - { 'Authorization' => 'bar' } - ] - end - let(:client_secret_args) do - [ - 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclient-secret', - 'baz', - { 'Authorization' => 'bar' } - ] - end - let(:claim_mapping_args) do - [ - 'http://localhost:3000/secrets/cucumber/variable/conjur%2Fauthn-oidc%2Ffoo%2Fclaim-mapping', - 'bing', - { 'Authorization' => 'bar' } - ] - end - let(:policy_response) { double(RestClient::Response, code: 201, body: 'foo') } - let(:variable_response) { double(RestClient::Response, code: 201) } - let(:rest_client) do - class_double(RestClient).tap do |double| - allow(double).to receive(:post).with(*policy_load_args).and_return(policy_response) - allow(double).to receive(:post).with(*provider_uri_args).and_return(variable_response) - allow(double).to receive(:post).with(*client_id_args).and_return(variable_response) - allow(double).to receive(:post).with(*client_secret_args).and_return(variable_response) - allow(double).to receive(:post).with(*claim_mapping_args).and_return(variable_response) - end - end + # it 'returns successfully' do + # response = factory.render_and_apply_policy( + # policy_load_path: 'bar', + # policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), + # variables: { 'id' => 'foo', 'branch' => 'bar' }, + # account: 'cucumber', + # authorization: 'bar' + # ) + # expect(response.success?).to be(true) + # end + # end + # end - let(:factory_template) { JSON.parse(Base64.decode64(Factories::Templates::Authenticators::V1::AuthnOidc.data)) } - it 'returns successfully' do - policy_factory = DB::Repository::DataObjects::PolicyFactory.new( - policy: Base64.decode64(factory_template['policy']), - policy_branch: factory_template['policy_branch'], - schema: factory_template['schema'], - version: 'v1', - name: 'authn-oidc', - classification: 'authenticators', - description: '' - ) + # describe('.set_factory_variables') do + # let(:rest_client) do + # class_double(RestClient).tap do |double| + # rest_client_requests.each do |request, value| + # allow(double).to receive(:post).with(request, value, authorization).and_return(response) + # end + # end + # end + # let(:authorization) { { "Authorization"=>"baz" } } + # let(:rest_client_requests) do + # { + # 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Ffoo' => 'bing', + # 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Fbar' => 'bang' + # } + # end + # context 'when role is unauthorized' do + # let(:response) { double(RestClient::Response, code: 401) } + # it 'returns a failure response' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '', 'bar' => '' }, + # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(false) + # expect(response.status).to eq(:unauthorized) + # expect(response.message).to eq( + # "Role is unauthorized to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" + # ) + # end + # end + # context 'when role lacks privilege' do + # let(:response) { double(RestClient::Response, code: 403) } + # it 'returns a failure response' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '', 'bar' => '' }, + # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(false) + # expect(response.status).to eq(:forbidden) + # expect(response.message).to eq( + # "Role lacks the privilege to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" + # ) + # end + # end + # context 'when variable is not present' do + # let(:response) { double(RestClient::Response, code: 404, body: 'response') } + # it 'returns a failure response' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '', 'bar' => '' }, + # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(false) + # expect(response.status).to eq(:bad_request) + # expect(response.message).to eq( + # "Failed to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'. Status Code: '404', Response: 'response'" + # ) + # end + # end + # context 'when request is expected to be valid' do + # let(:response) { double(RestClient::Response, code: 201) } + # context 'when factory includes multiple variables' do + # it 'is successful' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '', 'bar' => '' }, + # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(true) + # end + # context 'when factory includes a single variables' do + # it 'is successful' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '' }, + # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(true) + # end + # end + # context 'when factory includes a variable not present in request' do + # it 'is successful' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '', 'bar' => '' }, + # factory_variables: { 'foo' => 'bing' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(true) + # end + # end + # context 'when request includes a value not present in the factory' do + # it 'is successful' do + # response = factory.set_factory_variables( + # schema_variables: { 'foo' => '' }, + # factory_variables: { 'foo' => 'bing', 'bing' => 'foo' }, + # variable_path: 'foo/bar', + # account: 'cucumber', + # authorization: 'baz' + # ) + # expect(response.success?).to eq(true) + # end + # end + # end + # end + # end - result = factory.call( - factory_template: policy_factory, - request_body: { - 'id' => 'foo', - 'variables' => { - 'provider-uri' => 'foo', - 'client-id' => 'bar', - 'client-secret' => 'baz', - 'claim-mapping' => 'bing' - } - }.to_json, - account: 'cucumber', - authorization: 'bar' - ) - expect(result.success?).to eq(true) - expect(result.result).to eq('foo') - end - end - end + # describe('.call') do + # context 'when policy factory is only a policy' do + # it 'loads the appropriate policy' do + # # factory.call( + # # factory_template: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)), + # # request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json + # # ) + # end + # end + # end end diff --git a/spec/app/domain/factories/renderer_spec.rb b/spec/app/domain/factories/renderer_spec.rb new file mode 100644 index 0000000000..810f1d906b --- /dev/null +++ b/spec/app/domain/factories/renderer_spec.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe(Factories::Renderer) do + subject { Factories::Renderer.new } + describe '.render' do + context 'when template is valid' do + let(:template) do + <<~TEMPLATE + - !policy + id: <%= id %> + TEMPLATE + end + context 'when all variables are present' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: 'foo' }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: foo\n") + end + end + context 'when variables are missing' do + it 'returns an error' do + response = subject.render(template: template, variables: {}) + expect(response.success?).to be_falsey + expect(response.message).to eq("Required template variable 'id' is missing") + end + end + context 'when variable is nil' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: nil }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: \n") + end + end + context 'when extra variables are present' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: 'foo', bar: 'baz' }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: foo\n") + end + end + context 'when variables are not strings' do + context 'when variable is an integer' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: 1 }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: 1\n") + end + end + context 'when variable is a boolean' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: false }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: false\n") + end + end + context 'when variable is an array' do + it 'successfully renders template' do + response = subject.render(template: template, variables: { id: %w[foo bar] }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: [\"foo\", \"bar\"]\n") + end + end + end + end + context 'when template is invalid' do + context 'when there is not ERB closing tag' do + let(:template) do + <<~TEMPLATE + - !policy + id: <%= id + bar: baz + TEMPLATE + end + it 'the result is successful, does not perform substitution, and does not include the opening tag' do + response = subject.render(template: template, variables: { id: 'foo' }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: id\n bar: baz\n") + end + end + context 'when the template is missing an ERB opening tag' do + let(:template) do + <<~TEMPLATE + - !policy + id: id %> + bar: baz + TEMPLATE + end + it 'the result is successful, does not perform substitution, and includes the closing tag' do + response = subject.render(template: template, variables: { id: 'foo' }) + expect(response.success?).to be_truthy + expect(response.result).to eq("- !policy\n id: id %>\n bar: baz\n") + end + end + end + end +end From 30eb4a3c757a73a7019eedbd4b8f4ad058cadeca Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Tue, 11 Jul 2023 14:04:37 -0600 Subject: [PATCH 42/42] Finished unit tests for CreateFromPolicyFactory --- .../factories/create_from_policy_factory.rb | 43 +- app/domain/responses.rb | 22 +- .../create_from_policy_factory_spec.rb | 634 ++++++++++-------- spec/app/domain/responses_spec.rb | 37 +- 4 files changed, 437 insertions(+), 299 deletions(-) diff --git a/app/domain/factories/create_from_policy_factory.rb b/app/domain/factories/create_from_policy_factory.rb index 6f8292bf80..371e7ead97 100644 --- a/app/domain/factories/create_from_policy_factory.rb +++ b/app/domain/factories/create_from_policy_factory.rb @@ -11,7 +11,6 @@ def self.filter_input(str) end end class CreateFromPolicyFactory - def initialize(renderer: Factories::Renderer.new, http: RestClient, schema_validator: JSONSchemer, utilities: Factories::Utilities) @renderer = renderer @http = http @@ -38,8 +37,11 @@ def call(factory_template:, request_body:, account:, authorization:) # Filter non-alpha-numeric, dash or underscore characters from inputs values (to prevent injection attacks). template_variables = body_variables .transform_keys { |key| key.to_s.underscore } - .transform_values do |value| - if value.is_a?(Hash) + .each_with_object({}) do |(key, value), rtn| + # Only strip values that are rendered in the policy (not Conjur secret values) + rtn[key] = if key == 'variables' + value + elsif value.is_a?(Hash) value.transform_values { |internal_value| @utilities.filter_input(internal_value.to_s) } else @utilities.filter_input(value.to_s) @@ -108,7 +110,7 @@ def validate_and_transform_request(schema:, params:) end else { - message: "Generic JSON Schema validation error: type => '#{error['type']}', details => '#{error['type'].inspect}'" + message: "Validation error: '#{error['data_pointer']}' must be a #{error['type']}" } end end @@ -128,19 +130,14 @@ def render_and_apply_policy(policy_load_path:, policy_template:, variables:, acc ) rescue RestClient::ExceptionWithResponse => e case e.response.code - when 400 - return @failure.new( - { message: "Failed to apply generated Policy to '#{policy_load_path}'", - request_error: e.response.body }, status: :bad_request - ) when 401 return @failure.new( - { message: "Unauthorized to apply generated policy to '#{policy_load_path}'", + { message: 'Authentication failed', request_error: e.response.body }, status: :unauthorized ) when 403 return @failure.new( - { message: "Forbidden to apply generated policy to '#{policy_load_path}'", + { message: "Applying generated policy to '#{policy_load_path}' is not allowed", request_error: e.response.body }, status: :forbidden ) when 404 @@ -150,10 +147,15 @@ def render_and_apply_policy(policy_load_path:, policy_template:, variables:, acc ) else return @failure.new( - { message: "Failed to apply generated policy to '#{policy_load_path}'. Status Code: '#{response.code}, Response: '#{response.body}''", + { message: "Failed to apply generated policy to '#{policy_load_path}'", request_error: e.to_s }, status: :bad_request ) end + rescue => e + return @failure.new( + { message: "Failed to apply generated policy to '#{policy_load_path}'", + request_error: e.to_s }, status: :bad_request + ) end @success.new(response.body) @@ -161,30 +163,33 @@ def render_and_apply_policy(policy_load_path:, policy_template:, variables:, acc end def set_factory_variables(schema_variables:, factory_variables:, variable_path:, authorization:, account:) + # Only set secrets defined in the policy schema_variables.each_key do |factory_variable| - next unless factory_variables.key?(factory_variable) - variable_id = @uri.encode_www_form_component("#{variable_path}/#{factory_variable}") secret_path = "secrets/#{account}/variable/#{variable_id}" - response = @http.post( + @http.post( "http://localhost:3000/#{secret_path}", factory_variables[factory_variable].to_s, { 'Authorization' => authorization } ) - next if response.code == 201 - - case response.code + rescue RestClient::ExceptionWithResponse => e + case e.response.code when 401 return @failure.new("Role is unauthorized to set variable: '#{secret_path}'", status: :unauthorized) when 403 return @failure.new("Role lacks the privilege to set variable: '#{secret_path}'", status: :forbidden) else return @failure.new( - "Failed to set variable: '#{secret_path}'. Status Code: '#{response.code}', Response: '#{response.body}'", + "Failed to set variable: '#{secret_path}'. Status Code: '#{e.response.code}', Response: '#{e.response.body}'", status: :bad_request ) end + rescue => e + return @failure.new( + { message: "Failed set variable '#{secret_path}'", + request_error: e.to_s }, status: :bad_request + ) end @success.new('Variables successfully set') end diff --git a/app/domain/responses.rb b/app/domain/responses.rb index 26386aa780..2bb627392c 100644 --- a/app/domain/responses.rb +++ b/app/domain/responses.rb @@ -26,7 +26,7 @@ def bind(&_block) # Responsible for handling "failed" requests. # Log level and Response code are both option. class FailureResponse - attr_reader :message, :status + attr_reader :status def initialize(message, level: :warn, status: :unauthorized) @message = message @@ -42,18 +42,22 @@ def level @level.to_sym end + def message + case @message + when Array + @message + when Hash + @message + else + { message: @message.to_s } + end + end + def to_h { code: HTTP::Response::Status::SYMBOL_CODES[@status] }.tap do |rtn| - case @message - when Array - rtn[:errors] = @message - when Hash - rtn[:error] = @message - else - rtn[:error] = { message: @message.to_s } - end + rtn[:error] = message end end diff --git a/spec/app/domain/factories/create_from_policy_factory_spec.rb b/spec/app/domain/factories/create_from_policy_factory_spec.rb index fdf1785510..9ea7e76fae 100644 --- a/spec/app/domain/factories/create_from_policy_factory_spec.rb +++ b/spec/app/domain/factories/create_from_policy_factory_spec.rb @@ -4,296 +4,394 @@ RSpec.describe(Factories::CreateFromPolicyFactory) do let(:rest_client) { spy(RestClient) } - let(:factory) { Factories::CreateFromPolicyFactory.new(http: rest_client) } - # let(:simple_decoded_factory) { JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) } - let(:simple_factory) do - decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) - DB::Repository::DataObjects::PolicyFactory.new( - schema: decoded_factory['schema'], - policy: Base64.decode64(decoded_factory['policy']), - policy_branch: decoded_factory['policy_branch'] - ) - end - - describe('.call') do - let(:response) do - factory.call( - factory_template: simple_factory, + subject do + Factories::CreateFromPolicyFactory + .new(http: rest_client) + .call( + factory_template: factory_template, request_body: request, account: 'rspec', authorization: 'foo-bar' ) - end + end - context 'when request is invalid' do - context 'when request body is missing' do - let(:request) { nil } - it 'returns a failure response' do - expect(response.success?).to be(false) - expect(response.message).to eq('Request body must be JSON') - expect(response.status).to eq(:bad_request) - end + describe('.call') do + context 'when using a simple factory' do + let(:factory_template) do + decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)) + DB::Repository::DataObjects::PolicyFactory.new( + schema: decoded_factory['schema'], + policy: Base64.decode64(decoded_factory['policy']), + policy_branch: decoded_factory['policy_branch'] + ) end - context 'when request body is empty' do - let(:request) { '' } - it 'returns a failure response' do - expect(response.success?).to be(false) - expect(response.message).to eq('Request body must be JSON') - expect(response.status).to eq(:bad_request) + context 'when request is invalid' do + context 'when request body is missing' do + let(:request) { nil } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: 'Request body must be JSON' }) + expect(subject.status).to eq(:bad_request) + end + end + context 'when request body is empty' do + let(:request) { '' } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: 'Request body must be JSON' }) + expect(subject.status).to eq(:bad_request) + end + end + context 'when request body is malformed JSON' do + let(:request) { '{"foo": "bar }' } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: 'Request body must be valid JSON' }) + expect(subject.status).to eq(:bad_request) + end end + context 'when request body is missing keys' do + let(:request) { { id: 'foo' }.to_json } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "A value is required for 'branch'", key: 'branch' }]) + expect(subject.status).to eq(:bad_request) + end + end + context 'when request body is missing values' do + let(:request) { { id: '', branch: 'foo' }.to_json } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) + expect(subject.status).to eq(:bad_request) + end + end + context 'when the request body includes invalid values' do + let(:request) { { id: 'foo%', branch: 'b@r' }.to_json } + it 'submits the expected policy to Conjur with invalid characters removed' do + expect(subject.success?).to be(true) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/rspec/policy/br', "- !user\n id: foo\n", { 'Authorization' => 'foo-bar' }) + end + end + context 'when request body is valid' do + let(:request) { { id: 'foo', branch: 'bar' }.to_json } + it 'submits the expected policy to Conjur' do + expect(subject.success?).to be(true) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/rspec/policy/bar', "- !user\n id: foo\n", { 'Authorization' => 'foo-bar' }) + end + context 'when inputs include a hash (ex. for annotations)' do + let(:request) { { id: 'foo', branch: 'bar', annotations: { 'foo' => 'bar', 'bing' => 'bang' } }.to_json } + it 'submits the expected policy to Conjur' do + expect(subject.success?).to be(true) + expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/rspec/policy/bar', "- !user\n id: foo\n annotations:\n foo: bar\n bing: bang\n", { 'Authorization' => 'foo-bar' }) + end + end + context 'when the Conjur API returns an error' do + context 'when credentials are invalid' do + it 'returns a failure response' do + allow(rest_client).to receive(:post).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 401, body: 'foo') + ) + ) + + expect(subject.success?).to be(false) + expect(subject.message[:message]).to eq('Authentication failed') + expect(subject.status).to eq(:unauthorized) + end + end + context 'when role is not permitted to apply the policy' do + it 'returns a failure response' do + allow(rest_client).to receive(:post).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 403, body: 'foo') + ) + ) + + expect(subject.success?).to be(false) + expect(subject.message).to include({ + message: "Applying generated policy to 'bar' is not allowed", + request_error: 'foo' + }) + expect(subject.status).to eq(:forbidden) + end + end + context 'when policy refers to invalid roles or resources' do + it 'returns a failure response' do + allow(rest_client).to receive(:post).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 404, body: 'foo') + ) + ) + + expect(subject.success?).to be(false) + expect(subject.message[:message]).to eq("Unable to apply generated policy to 'bar'") + expect(subject.status).to eq(:not_found) + end + end + context 'when policy load is currently in progress' do + it 'returns a failure response' do + allow(rest_client).to receive(:post).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 409, body: 'foo') + ) + ) + + expect(subject.success?).to be(false) + expect(subject.message[:message]).to eq("Failed to apply generated policy to 'bar'") + expect(subject.status).to eq(:bad_request) + end + end + context 'when a connection timeout error occurs' do + it 'returns a failure response' do + allow(rest_client).to receive(:post).and_raise( + RestClient::ServerBrokeConnection.new + ) + + expect(subject.success?).to be(false) + expect(subject.message[:message]).to eq("Failed to apply generated policy to 'bar'") + expect(subject.status).to eq(:bad_request) + end + end + end + end + end + end + context 'when using a complex factory' do + let(:factory_template) do + decoded_factory = JSON.parse(Base64.decode64(Factories::Templates::Connections::V1::Database.data)) + DB::Repository::DataObjects::PolicyFactory.new( + schema: decoded_factory['schema'], + policy: Base64.decode64(decoded_factory['policy']), + policy_branch: decoded_factory['policy_branch'] + ) end - context 'when request body is malformed JSON' do - let(:request) { '{"foo": "bar }' } + let(:request) { { id: 'bar', branch: 'foo', variables: variables }.to_json } + context 'when request body is missing values' do + let(:variables) { { port: '1234', url: 'http://localhost', username: 'super-user' } } it 'returns a failure response' do - expect(response.success?).to be(false) - expect(response.message).to eq('Request body must be valid JSON') - expect(response.status).to eq(:bad_request) + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "A value is required for '/variables/password'", key: '/variables/password' }]) + expect(subject.status).to eq(:bad_request) end end - context 'when request body is missing keys' do - let(:request) { { id: 'foo' }.to_json } - it 'returns a failure response' do - expect(response.success?).to be(false) - expect(response.message).to eq([{ message: "A value is required for 'branch'", key: 'branch' }]) - expect(response.status).to eq(:bad_request) + context 'when variable value is not a string' do + context 'when value is an integer' do + let(:variables) { { port: 1234, url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "Validation error: '/variables/port' must be a string" }]) + expect(subject.status).to eq(:bad_request) + end + end + context 'when value is a boolean' do + let(:variables) { { port: true, url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "Validation error: '/variables/port' must be a string" }]) + expect(subject.status).to eq(:bad_request) + end + end + context 'when value is null' do + let(:variables) { { port: nil, url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + it 'returns a failure response' do + expect(subject.success?).to be(false) + expect(subject.message).to eq([{ message: "Validation error: '/variables/port' must be a string" }]) + expect(subject.status).to eq(:bad_request) + end end end - context 'when request body is missing values' do - let(:request) { { id: '', branch: 'foo' }.to_json } - it 'returns a failure response' do - expect(response.success?).to be(false) - expect(response.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) - expect(response.status).to eq(:bad_request) + context 'when request body includes required values' do + let(:variables) { { port: '1234', url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + it 'applies policy and variables' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) + + variables.each do |variable, value| + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2F#{variable}", + value, + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '') + ) + end + expect(subject.success?).to be(true) end end - context 'when request body is valid' do - let(:request) { { id: 'foo', branch: 'bar' }.to_json } - it 'submits the expected policy to Conjur' do - expect(response.success?).to be(true) - expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/rspec/policy/bar', "- !user\n id: foo\n", { 'Authorization' => 'foo-bar' }) + context 'when request body includes extra variable values' do + let(:variables) { { foo: 'bar', port: '1234', url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + # let(:request) { { id: 'bar', branch: 'foo', variables: variables }.to_json } + it 'only saves variables defined in the factory' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) + + variables.delete(:foo) + variables.each do |variable, value| + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2F#{variable}", + value, + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '') + ) + end + expect(subject.success?).to be(true) end end - end - end + context 'when role is not permitted to set variables' do + let(:variables) { { port: '1234', url: 'http://localhost', username: 'super-user', password: 'foo-bar' } } + context 'when role is not authorized' do + it 'applies policy and variables' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2Furl", + 'http://localhost', + { 'Authorization' => 'foo-bar' } + ).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 401, body: '') + ) + ) - # describe('.validate_and_transform_request') do - # context 'with a simple factory' do - # let(:validated) do - # factory.validate_and_transform_request( - # schema: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['schema'], - # params: params - # ) - # end - # context 'when request body is missing' do - # let(:params) { nil } - # it 'returns a failure response' do - # expect(validated.success?).to be(false) - # expect(validated.message).to eq("Request body must be JSON") - # expect(validated.status).to eq(:bad_request) - # end - # end - # context 'when request body is malformed JSON' do - # let(:params) { '{"foo": "bar }' } - # it 'returns a failure response' do - # expect(validated.success?).to be(false) - # expect(validated.message).to eq("Request body must be valid JSON") - # expect(validated.status).to eq(:bad_request) - # end - # end - # context 'when request body is missing keys' do - # let(:params) { { id: 'foo' }.to_json } - # it 'returns a failure response' do - # expect(validated.success?).to be(false) - # expect(validated.message).to eq([{ message: "A value is required for 'branch'", key: "branch" }]) - # expect(validated.status).to eq(:bad_request) - # end - # end - # context 'when request body is missing values' do - # let(:params) { { id: '', branch: 'foo' }.to_json } - # it 'returns a failure response' do - # expect(validated.success?).to be(false) - # expect(validated.message).to eq([{ message: "A value is required for 'id'", key: 'id' }]) - # expect(validated.status).to eq(:bad_request) - # end - # end - # context 'when request body is valid' do - # let(:params) { { id: 'foo', branch: 'bar' }.to_json } - # it 'returns a failure response' do - # expect(validated.success?).to be(true) - # validated.bind {|result| expect(result).to eq({ 'id' => 'foo', 'branch' => 'bar' }) } - # end - # end - # end - # end + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: "Role is unauthorized to set variable: 'secrets/rspec/variable/foo%2Fbar%2Furl'" }) + expect(subject.status).to eq(:unauthorized) + end + end + context 'when role lacks required privileges' do + it 'applies policy and variables' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) - # describe('.render_and_apply_policy') do - # # Technically we should mock the Factories::Renderer to make this truely a unit - # # test. I'm including it here to avoid needing to maintain an extra interface. - # context 'The expected data is posted to the Conjur API' do - # it 'loads the approprate policy' do - # factory.render_and_apply_policy( - # policy_load_path: 'bar', - # policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), - # variables: { 'id' => 'foo', 'branch' => 'bar' }, - # account: 'cucumber', - # authorization: 'bar' - # ) - # expect(rest_client).to have_received(:post).with('http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}) - # end - # end + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2Furl", + 'http://localhost', + { 'Authorization' => 'foo-bar' } + ).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 403, body: '') + ) + ) - # context 'when response is valid' do - # let(:args) do - # ['http://localhost:3000/policies/cucumber/policy/bar', "- !user\n id: foo\n", {"Authorization"=>"bar"}] - # end - # let(:response) { double(RestClient::Response, code: 201, body: 'foo') } - # let(:rest_client) do - # class_double(RestClient).tap do |double| - # allow(double).to receive(:post).with(*args).and_return(response) - # end - # end + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: "Role lacks the privilege to set variable: 'secrets/rspec/variable/foo%2Fbar%2Furl'" }) + expect(subject.status).to eq(:forbidden) + end + end + context 'when variable is missing' do + it 'fails with an appropriate error' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) + + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2Furl", + 'http://localhost', + { 'Authorization' => 'foo-bar' } + ).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 404, body: '') + ) + ) + + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: "Failed to set variable: 'secrets/rspec/variable/foo%2Fbar%2Furl'. Status Code: '404', Response: ''" }) + expect(subject.status).to eq(:bad_request) + end + end + context 'when there is a variable missing' do + it 'applies policy and variables' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) + + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2Furl", + 'http://localhost', + { 'Authorization' => 'foo-bar' } + ).and_raise( + RestClient::BadRequest.new( + double(RestClient::Response, code: 404, body: '') + ) + ) - # it 'returns successfully' do - # response = factory.render_and_apply_policy( - # policy_load_path: 'bar', - # policy_template: Base64.decode64(JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data))['policy']), - # variables: { 'id' => 'foo', 'branch' => 'bar' }, - # account: 'cucumber', - # authorization: 'bar' - # ) - # expect(response.success?).to be(true) - # end - # end - # end + expect(subject.success?).to be(false) + expect(subject.message).to eq({ message: "Failed to set variable: 'secrets/rspec/variable/foo%2Fbar%2Furl'. Status Code: '404', Response: ''" }) + expect(subject.status).to eq(:bad_request) + end + end + context 'when there is a timeout attempting to set the secret' do + it 'returns the appropriate error' do + allow(rest_client).to receive(:post) + .with( + 'http://localhost:3000/policies/rspec/policy/foo', + "- !policy\n id: bar\n annotations:\n factory: connections/database\n body:\n - &variables\n - !variable url\n - !variable port\n - !variable username\n - !variable password\n\n - !group consumers\n - !group administrators\n\n # consumers can read and execute\n - !permit\n resource: *variables\n privileges: [ read, execute ]\n role: !group consumers\n\n # administrators can update (and read and execute, via role grant)\n - !permit\n resource: *variables\n privileges: [ update ]\n role: !group administrators\n\n # administrators has role consumers\n - !grant\n member: !group administrators\n role: !group consumers\n", + { 'Authorization' => 'foo-bar' } + ).and_return( + double(RestClient::Response, code: 201, body: '{"created_roles":{},"version":13}') + ) - # describe('.set_factory_variables') do - # let(:rest_client) do - # class_double(RestClient).tap do |double| - # rest_client_requests.each do |request, value| - # allow(double).to receive(:post).with(request, value, authorization).and_return(response) - # end - # end - # end - # let(:authorization) { { "Authorization"=>"baz" } } - # let(:rest_client_requests) do - # { - # 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Ffoo' => 'bing', - # 'http://localhost:3000/secrets/cucumber/variable/foo%2Fbar%2Fbar' => 'bang' - # } - # end - # context 'when role is unauthorized' do - # let(:response) { double(RestClient::Response, code: 401) } - # it 'returns a failure response' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '', 'bar' => '' }, - # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(false) - # expect(response.status).to eq(:unauthorized) - # expect(response.message).to eq( - # "Role is unauthorized to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" - # ) - # end - # end - # context 'when role lacks privilege' do - # let(:response) { double(RestClient::Response, code: 403) } - # it 'returns a failure response' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '', 'bar' => '' }, - # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(false) - # expect(response.status).to eq(:forbidden) - # expect(response.message).to eq( - # "Role lacks the privilege to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'" - # ) - # end - # end - # context 'when variable is not present' do - # let(:response) { double(RestClient::Response, code: 404, body: 'response') } - # it 'returns a failure response' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '', 'bar' => '' }, - # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(false) - # expect(response.status).to eq(:bad_request) - # expect(response.message).to eq( - # "Failed to set variable: 'secrets/cucumber/variable/foo%2Fbar%2Ffoo'. Status Code: '404', Response: 'response'" - # ) - # end - # end - # context 'when request is expected to be valid' do - # let(:response) { double(RestClient::Response, code: 201) } - # context 'when factory includes multiple variables' do - # it 'is successful' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '', 'bar' => '' }, - # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(true) - # end - # context 'when factory includes a single variables' do - # it 'is successful' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '' }, - # factory_variables: { 'foo' => 'bing', 'bar' => 'bang' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(true) - # end - # end - # context 'when factory includes a variable not present in request' do - # it 'is successful' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '', 'bar' => '' }, - # factory_variables: { 'foo' => 'bing' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(true) - # end - # end - # context 'when request includes a value not present in the factory' do - # it 'is successful' do - # response = factory.set_factory_variables( - # schema_variables: { 'foo' => '' }, - # factory_variables: { 'foo' => 'bing', 'bing' => 'foo' }, - # variable_path: 'foo/bar', - # account: 'cucumber', - # authorization: 'baz' - # ) - # expect(response.success?).to eq(true) - # end - # end - # end - # end - # end + allow(rest_client).to receive(:post) + .with( + "http://localhost:3000/secrets/rspec/variable/foo%2Fbar%2Furl", + 'http://localhost', + { 'Authorization' => 'foo-bar' } + ).and_raise( + RestClient::ServerBrokeConnection.new + ) - # describe('.call') do - # context 'when policy factory is only a policy' do - # it 'loads the appropriate policy' do - # # factory.call( - # # factory_template: JSON.parse(Base64.decode64(Factories::Templates::Core::V1::User.data)), - # # request_body: { 'id' => 'foo', 'branch' => 'bar' }.to_json - # # ) - # end - # end - # end + expect(subject.success?).to be(false) + expect(subject.message).to include({ + message: "Failed set variable 'secrets/rspec/variable/foo%2Fbar%2Furl'", + request_error: 'Server broke connection' + }) + expect(subject.status).to eq(:bad_request) + end + end + end + end + end end diff --git a/spec/app/domain/responses_spec.rb b/spec/app/domain/responses_spec.rb index 4129473ca5..06532a2f00 100644 --- a/spec/app/domain/responses_spec.rb +++ b/spec/app/domain/responses_spec.rb @@ -26,7 +26,7 @@ describe '.message' do it 'is the message set in the initializer' do - expect(failure.message).to eq('bar') + expect(failure.message).to eq({ message: 'bar' }) end end @@ -49,8 +49,39 @@ let(:failure) { FailureResponse.new(message, **initialize_arguments) } describe '.message' do - it 'is the message set in the initializer' do - expect(failure.message).to eq('baz') + context 'when message is set in the initializer' do + context 'when it is a string' do + it "is returned as a hash with the key 'message'" do + expect(failure.message).to eq({ message: 'baz' }) + end + end + context 'when it is a hash' do + let(:message) { { foo: 'baz' } } + it 'is returned as a hash' do + expect(failure.message).to eq({ foo: 'baz' }) + end + end + context 'when it is an array' do + let(:message) { [{ foo: 'baz' }] } + it 'is returned as an array' do + expect(failure.message).to eq([{ foo: 'baz' }]) + end + end + end + end + + describe '.to_h' do + let(:message) { 'baz' } + context 'when default status is used' do + it 'returns an error and code' do + expect(failure.to_h).to eq({ code: 403, error: { message: 'baz' } }) + end + end + context 'when defined status is used' do + let(:initialize_arguments) { { level: :debug, status: :bad_request } } + it 'returns an error and code' do + expect(failure.to_h).to eq({ code: 400, error: { message: 'baz' } }) + end end end