تخطَّ إلى المحتوى

Conjur

CyberArk Conjur is an open-source secrets management platform designed for modern cloud-native and containerized environments. It provides centralized control over sensitive credentials—database passwords, API keys, tokens, certificates—with powerful access controls based on machine identity and role-based access control (RBAC).

Conjur integrates seamlessly with Kubernetes, Docker, Ansible, Terraform, Jenkins, and other DevOps tools. It uses policy-as-code for flexible permission management and REST API for programmatic access, making it ideal for CI/CD pipelines and infrastructure automation.

GitHub: cyberark/conjur
License: LGPL v3
Container-Ready: Kubernetes, Docker, Docker Compose

  • Docker or Docker Compose
  • PostgreSQL 10+ (for persistence)
  • OpenSSL (for certificate generation)
# docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: conjur
      POSTGRES_PASSWORD: pg_password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  conjur:
    image: cyberark/conjur:latest
    command: server
    environment:
      CONJUR_DATA_KEY: ${CONJUR_DATA_KEY}
      RAILS_ENV: production
      DATABASE_URL: postgresql://postgres:pg_password@postgres/conjur
    ports:
      - "8080:80"
      - "8443:443"
    depends_on:
      - postgres
    volumes:
      - ./config:/etc/conjur/config
      - ./certificates:/etc/conjur/ssl

volumes:
  postgres_data:
# Add Conjur Helm repository
helm repo add conjur https://cyberark.github.io/conjur-helm
helm repo update

# Create namespace
kubectl create namespace conjur

# Install Conjur
helm install conjur conjur/conjur \
  --namespace conjur \
  --set dataKey=$(openssl rand -base64 32) \
  --set postgresql.postgresPassword=$(openssl rand -base64 32)

# Verify deployment
kubectl get pods -n conjur
kubectl get svc -n conjur
# Generate data key (used to encrypt secrets)
export CONJUR_DATA_KEY=$(openssl rand -base64 32)

# Run Conjur container
docker run -d \
  --name conjur \
  -p 8080:80 \
  -p 8443:443 \
  -e CONJUR_DATA_KEY=$CONJUR_DATA_KEY \
  -e RAILS_ENV=production \
  cyberark/conjur:latest server

# Initialize Conjur
docker exec conjur conjur db migrate
# Clone repository
git clone https://github.com/cyberark/conjur.git
cd conjur

# Install dependencies
bundle install

# Set up database
bundle exec rails db:create
bundle exec rails db:migrate

# Start development server
bundle exec rails s
# Initialize Conjur (creates admin user)
docker exec conjur conjur db migrate
docker exec conjur conjur db seed

# Get admin credentials
docker exec conjur conjur bin/conjur account create
# Via API
curl -X POST http://localhost:8080/api/v5/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "account": "production",
    "user_id": "admin"
  }'

# Response includes API key
{
  "created_at": "2024-01-15T10:30:00Z",
  "user_id": "admin",
  "api_key": "3zf8x2p9kq7w5m3n6r4j8y2l"
}
CommandPurposeExample
conjur account createCreate new accountconjur account create mycompany
conjur user createCreate user identityconjur user create appserver
conjur secret setStore secret valueconjur secret set db/password "secret123"
conjur secret getRetrieve secretconjur secret get db/password
conjur policy loadLoad RBAC policyconjur policy load root policy.yml
conjur policy appendAppend to policyconjur policy append root rules.yml
conjur host createCreate machine identityconjur host create app/production/server1
conjur host rotate-api-keyRotate host credentialsconjur host rotate-api-key app/production/server1
conjur check-privilegeVerify permissionsconjur check-privilege execute app/secret
# macOS
brew install conjur-cli

# Linux
curl https://releases.conjur.org/conjur-cli/install.sh | bash

# Docker
docker run --rm -it cyberark/conjur-cli:latest conjur --help
# Login to Conjur
export CONJUR_APPLIANCE_URL=http://localhost:8080
export CONJUR_ACCOUNT=production
export CONJUR_AUTHN_TOKEN_FILE=~/.conjur/token

conjur authn login -u admin
# Enter API key when prompted

# Verify authentication
conjur authn status
# Via CLI config
conjur config init \
  --url http://localhost:8080 \
  --account production

# Stores config in ~/.conjurrc
# Contents:
# ---
# appliance_url: http://localhost:8080
# account: production
# plugins_path: ~/.conjur/plugins
# Simple secret
conjur secret set database/password "MyP@ssw0rd123"

# Multi-line secret
conjur secret set tls/certificate @certificate.pem

# API call to store secret
curl -X POST http://localhost:8080/api/v5/secrets?variable_id=database/password \
  -H "Authorization: Token token=\"$CONJUR_TOKEN\"" \
  --data-urlencode 'value=MySecurePassword'
# Via CLI
conjur secret get database/password

# Via API
curl -H "Authorization: Token token=\"$CONJUR_TOKEN\"" \
  http://localhost:8080/api/v5/secrets?variable_id=database/password

# Response
MyP@ssw0rd123
# View secret access logs
conjur audit-role \
  --role-id=production/app/webserver \
  --verbose

# Via API
curl -H "Authorization: Token token=\"$CONJUR_TOKEN\"" \
  http://localhost:8080/api/v5/audit/events \
  ?resource_filter=database/password
# policy.yml
---
- !policy
  id: production
  body:
    # Define secret variable
    - !variable
      id: database/password
      description: Production database password
    
    # Define secret variable
    - !variable
      id: api/key
      description: External API key
    
    # Define role/group
    - !role
      id: app/webserver
      description: Web server application
    
    # Define permissions
    - !permit
      role: !role app/webserver
      privilege: [read, execute]
      resource: !variable database/password
    
    # Host identity for automation
    - !host
      id: app/automation/jenkins
      description: Jenkins CI/CD server
    
    # Grant permissions to host
    - !permit
      role: !host app/automation/jenkins
      privilege: [read, execute]
      resource: !variable api/key
# Load policy from file
conjur policy load root policy.yml

# Load policy from stdin
cat policy.yml | conjur policy load root

# API call
curl -X POST http://localhost:8080/api/v5/policies/production/policy \
  -H "Authorization: Token token=\"$CONJUR_TOKEN\"" \
  -H "Content-Type: application/x-yaml" \
  --data @policy.yml
# Append new rules (doesn't remove existing)
conjur policy append production new-rules.yml

# Replace entire policy (dangerous!)
conjur policy replace production complete-policy.yml

# Delete policy section
conjur policy delete production
---
- !policy
  id: database
  body:
    - !variable
      id: prod/postgres/password
    
    - !variable
      id: prod/postgres/connection-string
    
    - !role
      id: app/postgres-reader
    
    - !permit
      role: !role app/postgres-reader
      privilege: [read, execute]
      resource: !variable prod/postgres/password
    
    - !permit
      role: !role app/postgres-reader
      privilege: [read, execute]
      resource: !variable prod/postgres/connection-string
---
- !policy
  id: environments
  body:
    - !policy
      id: development
      body:
        - !variable database/password
        - !variable api/key
    
    - !policy
      id: staging
      body:
        - !variable database/password
        - !variable api/key
    
    - !policy
      id: production
      body:
        - !variable database/password
        - !variable api/key
# kubernetes-policy.yml
---
- !policy
  id: kubernetes
  body:
    - !variable
      id: k8s/namespace/default/secret
    
    - !host
      id: app/k8s/default/my-app
      annotations:
        authn-k8s/namespace: default
        authn-k8s/service-account: my-app
    
    - !permit
      role: !host app/k8s/default/my-app
      privilege: [read, execute]
      resource: !variable k8s/namespace/default/secret
apiVersion: v1
kind: Pod
metadata:
  name: app-with-conjur
  namespace: default
spec:
  serviceAccountName: my-app
  
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: CONJUR_APPLIANCE_URL
      value: "http://conjur.conjur.svc:80"
    - name: CONJUR_ACCOUNT
      value: "production"
    - name: CONJUR_AUTHN_LOGIN
      value: "host/app/k8s/default/my-app"
    - name: MY_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: injected-secret
          key: database-password
  
  - name: conjur-agent
    image: cyberark/conjur-authn-k8s-client:latest
    env:
    - name: CONJUR_APPLIANCE_URL
      value: "http://conjur.conjur.svc:80"
    - name: CONJUR_ACCOUNT
      value: "production"
    volumeMounts:
    - name: secret-volume
      mountPath: /shared
  
  volumes:
  - name: secret-volume
    emptyDir:
      medium: Memory
version: '3.8'

services:
  app:
    image: myapp:latest
    environment:
      CONJUR_APPLIANCE_URL: "http://conjur:80"
      CONJUR_ACCOUNT: "production"
      CONJUR_AUTHN_LOGIN: "host/app/docker/web"
    depends_on:
      - conjur
    command: sh -c "source /conjur-init.sh && npm start"
    volumes:
      - ./conjur-init.sh:/conjur-init.sh

conjur:
  image: cyberark/conjur:latest
  environment:
    CONJUR_DATA_KEY: ${CONJUR_DATA_KEY}
  volumes:
    - conjur_data:/opt/conjur/data
# Configure Conjur provider
terraform {
  required_providers {
    conjur = {
      source = "cyberark/conjur"
    }
  }
}

provider "conjur" {
  appliance_url    = "http://localhost:8080"
  account          = "production"
  login_id         = "terraform@conjur"
  api_key          = var.conjur_api_key
}

# Retrieve secret from Conjur
data "conjur_secret" "db_password" {
  name = "database/password"
}

# Use secret in resource
resource "aws_db_instance" "example" {
  master_password = data.conjur_secret.db_password.value
}
---
- name: Deploy application with secrets from Conjur
  hosts: webservers
  
  pre_tasks:
    - name: Retrieve database password from Conjur
      community.general.conjur_variable:
        name: database/password
        identity: ansible@conjur
        api_key: "{{ conjur_api_key }}"
        appliance_url: "{{ conjur_url }}"
      register: db_password
      no_log: true
  
  tasks:
    - name: Deploy with retrieved secret
      template:
        src: app.conf.j2
        dest: /etc/app/config.conf
      vars:
        database_password: "{{ db_password.value }}"
pipeline {
    agent any
    
    environment {
        CONJUR_APPLIANCE_URL = 'http://conjur:80'
        CONJUR_ACCOUNT = 'production'
        CONJUR_AUTHN_LOGIN = credentials('jenkins-conjur-login')
        CONJUR_AUTHN_API_KEY = credentials('jenkins-conjur-api-key')
    }
    
    stages {
        stage('Deploy') {
            steps {
                script {
                    withEnv(["DB_PASSWORD=${sh(
                        script: '''curl -X GET \\
                          -H "Authorization: Token token=\\"$CONJUR_TOKEN\\"" \\
                          $CONJUR_APPLIANCE_URL/api/v5/secrets?variable_id=database/password | base64 -d
                        ''',
                        returnStdout: true
                    ).trim()}"]) {
                        sh 'deploy.sh'
                    }
                }
            }
        }
    }
}
# rotation-policy.yml
---
- !policy
  id: rotation
  body:
    - !variable
      id: database/password
    
    # Schedule rotation
    - !secret
      id: database/rotation-schedule
      value: "0 2 * * 0"  # Every Sunday at 2 AM
# LDAP authentication
conjur authn ldap login -u username

# OIDC authentication
conjur authn oidc login -u username

# API key rotation
conjur host rotate-api-key app/automation/jenkins
# View all audit events
conjur audit-events \
  --resource-filter "variable" \
  --timestamp-from "2024-01-01T00:00:00Z"

# Export audit logs
curl -H "Authorization: Token token=\"$CONJUR_TOKEN\"" \
  "http://localhost:8080/api/v5/audit/resources" \
  > audit-report.json

# Create compliance report
conjur audit-summary --format=json > compliance-report.json
# config/secrets.yml
production:
  database:
    adapter: postgresql
    pool: 25
    max_connections: 100
    timeout: 5000
# Use local cache in applications
# Note: Cache should be short-lived for sensitive data
export CONJUR_SECRET_CACHE_TTL=300  # 5 minutes
# Check Conjur connectivity
curl -v http://localhost:8080/health

# Verify API key
conjur authn login -u admin --password $API_KEY

# Check authentication logs
docker logs conjur 2>&1 | grep -i auth
# Validate policy before loading
conjur policy validate policy.yml

# Check current policy
conjur policy show production

# Check user permissions
conjur check-privilege execute database/password
# Check database status
docker exec conjur-postgres psql -U postgres -c "\l"

# Verify database connectivity
curl http://localhost:8080/api/v5/health

# Check database logs
docker logs conjur-postgres
  1. Rotate credentials regularly - especially database passwords
  2. Use strong API keys - minimum 32 characters
  3. Restrict secret access - principle of least privilege
  4. Audit access - monitor all secret retrievals
  5. Use machine identities - avoid shared credentials
# Good: Granular policies
- !policy
  id: services/web
  body:
    - !host id: web-app-01
    - !host id: web-app-02
    - !variable id: database/password

# Bad: Overly permissive
- !policy
  id: services
  body:
    - !permit
      role: !policy services
      privilege: [read, execute]
      resource: !policy services
  1. High availability - Deploy multiple Conjur instances
  2. Regular backups - Backup PostgreSQL database
  3. TLS encryption - Use HTTPS in production
  4. Network segmentation - Restrict Conjur access by network
  • HashiCorp Vault (alternative)
  • AWS Secrets Manager (cloud-specific)
  • Kubernetes Secrets (basic)
  • 1Password Business (commercial)