How-tos

Declarative Configuration Import for Cloudentity

Cloudentity declarative configuration feature enables deployment agents to import and declaratively Cloudentity. Learn how to utilize the Cloudentity Helm Chart to speed up your workflow and declaratively configure your Cloudentity deployment.

About Configuration Import

In addition to Cloudentity’s import APIs, it is possible to configure your Cloudentity deployment declaratively using the acp-cd Helm Chart. The configuration import can be used for all Cloudentity deployment types including the Cloudentity SaaS deployment or Cloudentity deployment on Kubernetes.

The acp-cd Helm Chart is responsible for creating a Kubernetes job that seeds Cloudentity with configuration. You can, for example, define client applications, gateways (both for multi-tenant and single-tenant authorizers), policies, and APIs.

Declarative Configuration Capabilities

For a detailed list of entities that you can configure and for references, see:

Declarative configuration import allows you to use the GitOps approach. You can store configuration inside your Git repository and have your configuration and infrastructure as code. In this case, your Git repository acts as a single source of truth for your Cloudentity configuration. This leads to increased productivity for your teams, enhanced developer experience, improved stability and reliability, consistency, and many more.

Using declarative configuration import it is much easier to integrate with DevSecOps pipelines. You can execute the import job in a satellite environment that communicates with Cloudentity using the import API protected by the System tenant credentials.

Prerequisites

  1. Access to the Cloudentity tenant and its System workspace.

    System Workspace Access

    The importJob results in a call to Cloudentity’s import configuration API that is protected by System workspace credentials. System workspace access, by default, is hidden behind a feature flag. If you need access to the System workspace for your tenant, contact Cloudentity Sales team.

  2. Client application created in the System workspace.

    Client Configuration

    To be able to import the defined configuration, your import job needs to be able to authenticate to Cloudentity by calling the Cloudentity OAuth 2.0 token endpoint. Therefore, you need to allow the client credentials OAuth grant flow for your client application and assign the manage_configuration scope to it. To learn more about creating clients used for calling Cloudentity’s APIs, see the Getting started with Cloudentity REST API

  3. Kubernetes cluster up and running.

    For the purpose of this article, the acp-on-k8s environment is used that allows you to rapidly stand up your Cloudentity instance in your local development environment. For prerequisites and references for this deployment, visit a dedicated acp-on-k8s GitHub repository.

  4. Helm version 3.0 or subsequent.

Install acp-cd Helm Chart

  1. In your terminal, execute the following commands to get your Helm repository updated:

    helm repo add acp https://charts.cloudentity.io
    helm repo update
    
  2. Install your Helm Chart using the helm -n [NAMESPACE] install [RELEASE-NAME] [CHART] -f [VALUES.YAML FILE] command:

    helm -n [NAMESPACE] install [RELEASE-NAME] [CHART] -f [VALUES.YAML FILE] \
    --set clientCredentials.clientID={YOUR_IMPORT_JOB_CLIENT_IDENTIFIER} \
    --set clientCredentials.clientSecret={YOUR_IMPORT_JOB_CLIENT_SECRET} \
    --set clientCredentials.issuerURL={YOUR_ISSUER_URL} \
    

    Example:

    helm -n acp-system install sample-acp-cd-release acp/acp-cd -f values/acp-cd.yaml \
    --set clientCredentials.clientID=sample-import-client \
    --set clientCredentials.clientSecret=_D0Nze6aocqxW7hafyeJZarF-NQZi9FGDd2SIZgANhA \
    --set clientCredentials.issuerURL=https://example.com \
    

    Using the above command you install your acp-cd Helm Chart in the acp-system Kubernetes namespace as a part of the sample-acp-cd-release. To provide values for your chart, you use the acp-cd.yaml file. --set arguments are used to provide values for the client credentials of your import job client.

    Alternative Scenario

    Optionally, you can install your Helm Chart with the values for client credentials set in your custom values.yaml file.

    Helm resolves values in the following order:

    1. Values set using the --set argument

    2. Values from the custom values.yaml file

    3. Values from the default values.yaml file.

    Client Credentials and Security

    Be cautious while using client credentials of your import client. It is a client created in the System tenant, therefore, it can be used to access Cloudentity’s System APIs. For testing purposes, you can use --set arguments or provide values in the values.yaml file.

    Production environments should have Kubernetes secrets created manually with the clientCredentials.create value set to false in your values.yaml file.

    To increase security of secrets stored in your repository, it is recommended to encrypt your Kubernetes secrets. You can use tools like Mozilla SOPS or Bitnami Sealed Secrets to encrypt your secrets.

    When the secrets are applied to your Kubernetes deployment, the secrets are encrypted and visible as plain text. Anyone who is authorized to create a Pod in a namespace can read any secret in that namespace; this includes indirect access such as the ability to create a Deployment. To mitigate the risks, kubernetes recommends to:

    • Enable encryption at Rest for secrets.

    • Enable or configure RBAC rules that restrict reading data in secrets.

    • Where appropriate, use mechanisms such as RBAC to limit which principals are allowed to create or replace secrets.

    To learn more, visit Kubernetes secrets documentation

    Configure root CAs for ACP-CD HTTP client

    To provide the path to the root CAs to configure trusted certificates for acp-cd HTTP client, configure the following value in the values.yaml file:

    client:
      rootCA: "./ca.pem"
    

    Configure acp-cd client.

    You can configure acp-cd client by providing your configuration as part of the config value in the values.yaml file.

    Example:

    config:
      data:
        client:
          insecure_skip_verify: false # disable cert verification
    

Define Configuration Import

Below, you can find a couple of examples how to import configuration for objects, such as client applications, gateways, identity providers, and more. After you define your configuration import, upgrade your Helm Chart release

Identity Sources

To import an IDP configuration, add your IDP definition to your values.yaml file in the data section. See example below:

data:
  idps:
    - id: c49qvgb0djbgslsgvp3g
      tenant_id: { tid }
      authorization_server_id: { aid }
      name: GitHub Sample IDP
      disabled: false
      method: github
      attributes:
        - name: user_data.login
          description: Login
          type: string
          labels: null
        - name: user_data.id
          description: ID
          type: number
          labels: null
        - name: user_data.site_admin
          description: Site admin
          type: bool
          labels: null
        - name: user_data.name
          description: Name
          type: string
          labels: null
        - name: user_data.company
          description: Company
          type: string
          labels: null
        - name: user_data.email
          description: Email
          type: string
          labels: null
        - name: groups
          description: Groups
          type: string_array
          labels: null
      mappings:
        - source: user_data.name
          target: name
          type: string
          allow_weak_decoding: false
        - source: user_data.email
          target: email
          type: string
          allow_weak_decoding: false
        - source: groups
          target: groups
          type: string_array
          allow_weak_decoding: false
      static_amr: []
      transformer:
        enabled: false
        script: ""
      config:
        enable_stateful_ctx: false
        stateful_ctx_duration: 0s
      discovery_settings:
        domains: []
        instant_redirect: false
      token_exchange_settings:
        enabled: false
      identity_pool_id: null

Client Applications

To import client applications, add your application definition to your values.yaml file in the data section. See example below:

data:
  clients:
    - tenant_id: {tid}
      authorization_server_id: configuration-import
      client_id: acme-client
      client_secret: {sample-client-secret}
      token_endpoint_auth_method: client_secret_post
      system: false
      trusted: true
      client_name: Sample ACME client application
      application_type: web
      grant_types:
        - authorization_code
      response_types:
        - code
        - token
        - code
      scopes:
        - email
        - offline_access
        - openid

Reference

For detailed reference of client application configuration, see Create new OAuth client API reference

Authorizers

In Cloudentity, an authorizer object consists in fact of two entities: an actual authorizer, and a client application created for this authorizer in the System workspace. When an authorizer makes requests to Cloudentity to, for example, fetch authorization policies, it uses client credentials of its client application to authenticate to Cloudentity. Therefore, if you import an authorizer, you must import a client application for this authorizer as well.

Remember

Your client application must be created within the System workspace for your tenant. For the client configuration, set the authorization_server_id to system.

The client application must have the following scopes assigned: introspect_tokens, push_gateway_requests, read_gateway_configuration, write_gateway_configuration.

To import an authorizer and its client application, add their definition to your values.yaml file in the data section. See example below:

data:
  gateways:
    - tenant_id: {tid}
      authorization_server_id: configuration-import
      id: sample-pyron-authorizer
      client_id: pyron-authorizer-client
      client_secret: cf53caab-fb55-40a7-8c63-620ce11102e2
      name: Sample Pyron Authorizer
      description: Sample imported Pyron Authorizer
      type: pyron
      create_and_bind_services_automatically: true
  clients:
    - tenant_id: {tid}
      authorization_server_id: system
      client_id: pyron-authorizer-client
      client_secret: cf53caab-fb55-40a7-8c63-620ce11102e2
      token_endpoint_auth_method: client_secret_basic
      system: false
      trusted: false
      client_name: Pyron Authorizer client
      application_type: web
      grant_types:
        - client_credentials
      response_types:
        - code
      scopes:
        - introspect_tokens
        - push_gateway_requests
        - read_gateway_configuration
        - write_gateway_configuration

Reference

You can create authorizers of any type. The type parameter for your gateway object must be one of: apigeeedge, apigeex, aws, azure, istio, kong, pyron, standalone.

For a detailed reference regarding authorizers configuration, see Create gateway API reference

Authorization Policies

To import policies, add their definition to your values.yaml file in the data section. You can import both Cloudentity and REGO policies. See the examples below:

  • Cloudentity policies have language specified as cloudentity and are defined by validators:

    data:
      policies:
        - tenant_id: { tid }
          server_id: { aid }
          id: block_test_policy
          policy_name: block_test
          language: cloudentity
          type: api
          validators:
            - name: "false"
        - tenant_id: { tid }
          server_id: { aid }
          id: allow_test_policy
          policy_name: allow_test
          language: cloudentity
          type: api
          validators:
            - name: "true"
    
  • REGO policies have language specified as rego and are defined in the definition object containing REGO policy definition:

    data:
      policies:
        - tenant_id: { tid }
          server_id: { aid }
          id: auth_ctx_check_policy
          language: rego
          policy_name: check_email
          type: user
          definition: |
            package acp.authz
            default allow = false
            allow {
              input.authn_ctx.email == "test@gmail.com"
            }
            recovery = ["mfa"]        
    

Reference

For a detailed reference for authorization policies configuration, see Create policy API reference, Creating Cloudentity policies in the Visual Policy Editor, and Protecting Applications and APIs in Cloudentity Using Open Policy Agent.

API Groups and Services

Disabling Service Discovery

To fully comply with the GitOps philosophy, you can disable service discovery for your authorizer. In this case, the authorizer does not discover any services within your deployment and only the services that you import are available within Cloudentity.

If you want your Cloudentity to be declaratively configured, Cloudentity recommends disabling the service discovery. This way, you have full control over your changes history and your configuration changes are transparent.

To import API groups and services add their definition to your values.yaml file in the data section. See example below:

data:
   gateway_api_groups:
   - tenant_id: {tid}
      server_id: {aid}
      service_id: httpbin_service
      gateway_id: sample-pyron-authorizer
      name: default/httpbin_api_group
      id: c5n8akdcqsna55j67220
      apis:
         - method: GET
         path: /deny
         - method: GET
         path: /anything
   services:
   - id: httpbin_service
      tenant_id: {tid}
      authorization_server_id: {aid}
      gateway_id: sample-pyron-authorizer
      name: default/httpbin_service
      apis:
         - method: GET
         path: /deny
         can_have_policy: true
         policy_id: block_test_policy
         - method: GET
         path: /anything
         can_have_policy: true
         policy_id: allow_test_policy

What Should You Import

There are two scenarios according to which you should adjust your import:

  • Service discovery is disabled for your authorizer.

    You should import both API groups and services definition.

  • Service discovery is enabled for your authorizer.

    You should import only your services definition. API groups within your configured namespaces are discovered for your authorizer automatically.

Imported configuration from the above example contains:

  • httpbin API group for a sample Pyron Authorizer

    In the import example above, you can see that the API group has the c5n8akdcqsna55j67220 group identifier set. If we were to look at the Pyron Gateway, the API group identifier in the gateway would be the same. In your imported configuration, the API group identifiers must match API group identifiers from your gateway.

    403 NO RULE Status

    When an authorizer is set up to protect APIs and a request is made to an API, the authorizer responds with the 403 NO RULE status if:

    • The service is not added to configuration.

    • The configuration contains an incorrect API group identifier for the group and the authorizer fails to match the request to the API group.

    For testing purposes, this behavior can be adjusted by setting the ENFORCEMENT_ALLOW_UKNOWN parameter to true in your authorizer’s configuration. It causes the authorizer to not return the 403 NO RULE status when matching is done incorrectly.

  • httpbin service for a sample Pyron Authorizer

API Group and Service IDs for Istio Authorizer

For Istio Authorizer, API group identifiers or services identifiers are Base64 URL encoded SPIFFE IDs which are built being based on the service account of the protected pod. To avoid using long and unreadable API groups and service identifiers, Cloudentity supports Base64 encoding of SPIFFE IDs. To learn how to provide your API group or service identifier, see Declarative configuration import for Istio Authorizer article.

Upgrade acp-cd Chart

To upgrade your acp-cd Helm Chart values, execute the following command in your terminal:

helm -n [NAMESPACE] upgrade [RELEASE-NAME] [CHART] -f [VALUES.YAML FILE] \

Example:

helm -n acp-system upgrade sample-acp-cd-release acp/acp-cd -f values/acp-cd.yaml \

Your Helm Chart gets updated and the Kubernetes job uses Cloudentity import API to apply your configuration changes.