Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: release

on:
push:
tags:
- 'v*'

permissions:
contents: write

jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

- uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

test:
needs: goreleaser
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: ./
id: cac
with:
args: --help
- run: echo -e "${{ steps.cac.outputs.result }}"
name: print action output

negative-test:
needs: goreleaser
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: ./
id: cac
with:
args: pull --invalid
continue-on-error: true
- if: steps.cac.outcome == 'success'
name: fail on cac success
run: exit 1
- if: steps.cac.outcome == 'failure'
run: echo "cac failed as expected"
40 changes: 32 additions & 8 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,44 @@ permissions:
contents: read

jobs:
resolve-tag:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- id: tag
env:
GH_TOKEN: ${{ github.token }}
run: |
tag=$(gh release view --repo ${{ github.repository }} --json tagName -q .tagName 2>/dev/null || true)
if [ -z "$tag" ]; then
echo "no release found, will use default checkout ref"
else
echo "resolved release tag: $tag"
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"

test:
needs: resolve-tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./
id: cac
with:
args: --help
- run: echo -e "${{ steps.cac.outputs.result }}"
name: print action output
- uses: actions/checkout@v4
with:
ref: ${{ needs.resolve-tag.outputs.tag }}
- uses: ./
id: cac
with:
args: --help
- run: echo -e "${{ steps.cac.outputs.result }}"
name: print action output

negative-test:
needs: resolve-tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ needs.resolve-tag.outputs.tag }}
- uses: ./
id: cac
with:
Expand Down
38 changes: 38 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 2

project_name: cac

before:
hooks:
- go mod download

builds:
- id: cac
main: .
binary: cac
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
ldflags:
- -s -w

archives:
- id: cac
formats: [tar.gz]
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"

checksum:
name_template: 'checksums.txt'

changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- '^chore:'
18 changes: 0 additions & 18 deletions Dockerfile

This file was deleted.

10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cloudentity Configuration As Code (Early Access)
# SecureAuth Configuration As Code (Early Access)

This repository contains a CLI tool for managing Cloudentity configuration.
This repository contains a CLI tool for managing SecureAuth configuration.

## Installation

Expand Down Expand Up @@ -57,7 +57,7 @@ Prints help message with available commands and their parameters.
```bash
cac --help

Cloudentity configuration manager
SecureAuth configuration manager

Usage:
cac [command]
Expand All @@ -79,7 +79,7 @@ Use "cac [command] --help" for more information about a command.

### Pull

Pull configuration from Cloudentity and save it to a directory configured by `storage.dir_path`.
Pull configuration from SecureAuth and save it to a directory configured by `storage.dir_path`.

```bash
cac pull --help
Expand Down Expand Up @@ -159,7 +159,7 @@ The sample output in the `storage.dir_path` should look like:

### Push

Merge configuration from a directory structure and push it into Cloudentity.
Merge configuration from a directory structure and push it into SecureAuth.

```bash
cac push --help
Expand Down
76 changes: 71 additions & 5 deletions action.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,75 @@
name: 'Cloudentity CAC'
description: 'Manage Cloudentity configuration as code'
runs:
using: 'docker'
image: 'Dockerfile'
entrypoint: '/action-entrypoint.sh'
inputs:
args:
description: 'Arguments to pass to cac'
required: true
outputs:
result:
description: 'Result of the cac command'
description: 'Result of the cac command'
value: ${{ steps.run.outputs.result }}
runs:
using: 'composite'
steps:
- name: Restore cached binary
id: cache
uses: actions/cache@v4
with:
path: /tmp/cac
key: cac-${{ runner.os }}-${{ runner.arch }}-${{ github.action_ref || github.ref_name }}

- name: Download pre-built binary
id: download
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
continue-on-error: true
run: |
VERSION="${{ github.action_ref || github.ref_name }}"
REPO="${{ github.action_repository }}"

ARCH=$(uname -m)
case "$ARCH" in
x86_64) ARCH="amd64" ;;
aarch64) ARCH="arm64" ;;
esac
OS=$(uname -s | tr '[:upper:]' '[:lower:]')

URL="https://github.com/${REPO}/releases/download/${VERSION}/cac_${OS}_${ARCH}.tar.gz"
curl -sfL "$URL" -o /tmp/cac.tar.gz
tar -xzf /tmp/cac.tar.gz -C /tmp cac
chmod +x /tmp/cac
echo "Downloaded pre-built binary from ${URL}"

- name: Check for preinstalled Go
id: go-check
if: steps.download.outcome == 'failure'
shell: bash
run: |
if command -v go > /dev/null; then
echo "Using preinstalled Go: $(go version)"
echo "preinstalled=true" >> "$GITHUB_OUTPUT"
else
echo "preinstalled=false" >> "$GITHUB_OUTPUT"
fi

- name: Install Go
if: steps.download.outcome == 'failure' && steps.go-check.outputs.preinstalled != 'true'
uses: actions/setup-go@v5
with:
go-version-file: '${{ github.action_path }}/go.mod'

- name: Build from source
if: steps.download.outcome == 'failure'
shell: bash
run: |
cd "${{ github.action_path }}"
CGO_ENABLED=0 go build -o /tmp/cac .
echo "Built from source (no pre-built binary available for this ref)"

- name: Run cac
id: run
shell: bash
run: |
/tmp/cac ${{ inputs.args }} > /tmp/out
content=$(awk '{printf "%s\\n", $0}' /tmp/out)
echo "result=$content" >> "$GITHUB_OUTPUT"
68 changes: 59 additions & 9 deletions cmd/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,31 @@ import (
var (
diffCmd = &cobra.Command{
Use: "diff",
Short: "Compare configuration",
Short: "Compare configuration between two sources",
Long: `Compare configuration between two sources for a workspace or tenant.

--source and --target accept a source type, optionally prefixed with a profile
from --config using the form "[profile@]source-type".

Source types:
local - configuration read from local files
remote - configuration fetched from the SecureAuth server
merged - local files merged on top of remote configuration

Examples:
# Compare local files against the remote server
cac --config ./cac.yaml --profile dev --workspace demo diff --source local --target remote

# Compare two profiles' remote configurations
cac --config ./cac.yaml --workspace demo diff --source dev@remote --target prod@remote

# Compare merged view against the remote server, only for clients and policies
cac --config ./cac.yaml --profile dev --workspace demo diff \
--source merged --target remote --filter clients,policies

# Write the diff to a file
cac --config ./cac.yaml --profile dev --workspace demo diff \
--source local --target remote --out diff.txt`,
RunE: func(cmd *cobra.Command, args []string) error {
var (
app *cac.Application
Expand Down Expand Up @@ -87,14 +111,40 @@ var (
)

func init() {
diffCmd.PersistentFlags().StringVar(&diffConfig.Source, "source", "", "Source profile name")
diffCmd.PersistentFlags().StringVar(&diffConfig.Target, "target", "", "Target profile name")
diffCmd.PersistentFlags().BoolVar(&diffConfig.Colors, "colors", true, "Colorize output")
diffCmd.PersistentFlags().BoolVar(&diffConfig.OnlyPresent, "only-present", false, "Compare only resources present at source")
diffCmd.PersistentFlags().StringSliceVar(&diffConfig.Filters, "filter", []string{}, "Compare only selected resources")
diffCmd.PersistentFlags().StringVar(&diffConfig.Out, "out", "-", "Diff output. It can be a file or '-' for stdout")
diffCmd.PersistentFlags().BoolVar(&diffConfig.WithSecrets, "with-secrets", false, "Compare secrets")
diffCmd.PersistentFlags().BoolVar(&diffConfig.FilterVolatile, "no-volatile", false, "Ignore volatile fields")
diffCmd.PersistentFlags().StringVar(&diffConfig.Source, "source", "", `Source of the comparison (required). Format: [profile@]source-type
Source types: local, remote, merged
Examples:
--source local
--source remote
--source merged
--source dev@remote`)
diffCmd.PersistentFlags().StringVar(&diffConfig.Target, "target", "", `Target of the comparison (required). Format: [profile@]source-type
Source types: local, remote, merged
Examples:
--target remote
--target prod@remote
--target merged`)
diffCmd.PersistentFlags().BoolVar(&diffConfig.Colors, "colors", true, `Colorize the diff output (default true).
Example: --colors=false`)
diffCmd.PersistentFlags().BoolVar(&diffConfig.OnlyPresent, "only-present", false, `Only diff resources that are present in the source; ignore resources that only exist in the target.
Example: --only-present`)
diffCmd.PersistentFlags().StringSliceVar(&diffConfig.Filters, "filter", []string{}, `Restrict the comparison to selected top-level resources (comma-separated or repeated).
Workspace resources: clients, idps, claims, custom_apps, gateways, policies, policy_execution_points,
pools, scopes (alias of scopes_without_service), scripts, script_execution_points,
server_consent, servers_bindings, services, theme_binding, webhooks,
ciba (alias of ciba_authentication_service)
Tenant resources: pools, schemas, mfa_methods, themes, servers
Examples:
--filter clients
--filter clients,idps,policies`)
diffCmd.PersistentFlags().StringVar(&diffConfig.Out, "out", "-", `Diff output destination: a file path or '-' for stdout.
Examples:
--out - (stdout)
--out ./diff.txt (file)`)
diffCmd.PersistentFlags().BoolVar(&diffConfig.WithSecrets, "with-secrets", false, `Include secret fields in the comparison.
Example: --with-secrets`)
diffCmd.PersistentFlags().BoolVar(&diffConfig.FilterVolatile, "no-volatile", false, `Ignore volatile fields (e.g. timestamps, generated IDs) when comparing.
Example: --no-volatile`)

mustMarkRequired(diffCmd, "source", "target")
}
Loading
Loading