prvng_platform/oci-registry/scripts/configure-policies.nu
2025-10-07 10:59:52 +01:00

368 lines
10 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env nu
# Configure access policies for OCI registry namespaces
export def main [
--registry-url: string = "localhost:5000"
--registry-type: string = "zot"
--admin-password: string = "admin"
] {
print "🔒 Configuring OCI registry access policies..."
print $" Registry: ($registry_url)"
print $" Type: ($registry_type)\n"
let policies = get-policy-definitions
match $registry_type {
"zot" => {
configure-zot-policies $registry_url $policies
}
"harbor" => {
configure-harbor-policies $registry_url $policies $admin_password
}
"distribution" => {
configure-distribution-policies $registry_url $policies
}
_ => {
print $"⚠ Unknown registry type: ($registry_type)"
}
}
print "\n✅ Policy configuration complete!"
}
def get-policy-definitions [] -> list {
[
{
namespace: "provisioning-extensions"
access: {
authenticated: {
read: true
write: true
delete: true
}
anonymous: {
read: false
write: false
delete: false
}
}
users: [
{name: "provisioning", role: "admin"}
{name: "developer", role: "developer"}
]
webhooks: [
{
event: "push"
url: "http://orchestrator:8080/registry/events/push"
}
{
event: "delete"
url: "http://orchestrator:8080/registry/events/delete"
}
]
}
{
namespace: "provisioning-kcl"
access: {
authenticated: {
read: true
write: true
delete: false
}
anonymous: {
read: false
write: false
delete: false
}
}
users: [
{name: "provisioning", role: "admin"}
{name: "developer", role: "developer"}
]
webhooks: [
{
event: "push"
url: "http://orchestrator:8080/registry/events/push"
}
]
}
{
namespace: "provisioning-platform"
access: {
authenticated: {
read: true
write: false
delete: false
}
anonymous: {
read: false
write: false
delete: false
}
}
users: [
{name: "provisioning", role: "admin"}
]
webhooks: [
{
event: "push"
url: "http://orchestrator:8080/registry/events/push"
}
]
}
{
namespace: "provisioning-test"
access: {
authenticated: {
read: true
write: true
delete: true
}
anonymous: {
read: true
write: false
delete: false
}
}
users: [
{name: "provisioning", role: "admin"}
{name: "developer", role: "developer"}
{name: "tester", role: "developer"}
]
webhooks: []
}
]
}
def configure-zot-policies [registry_url: string, policies: list] {
print "Configuring Zot policies..."
print "\n Zot policies are configured in config.json"
print " The following policies are defined:\n"
for policy in $policies {
print $"📦 ($policy.namespace):"
print $" Authenticated users:"
print $" Read: ($policy.access.authenticated.read)"
print $" Write: ($policy.access.authenticated.write)"
print $" Delete: ($policy.access.authenticated.delete)"
print $" Anonymous users:"
print $" Read: ($policy.access.anonymous.read)"
print $" Users: ($policy.users | get name | str join ', ')"
if ($policy.webhooks | length) > 0 {
print $" Webhooks: ($policy.webhooks | length) configured"
}
print ""
}
print " To update policies, edit zot/config.json and restart the registry"
}
def configure-harbor-policies [
registry_url: string
policies: list
admin_password: string
] {
print "Configuring Harbor policies via API...\n"
let auth = $"admin:($admin_password)" | encode base64
for policy in $policies {
print $"📦 Configuring ($policy.namespace)..."
# Get project ID
let project_id = get-harbor-project-id $registry_url $policy.namespace $auth
if ($project_id | is-empty) {
print $" ⚠ Project not found, skipping"
continue
}
# Configure RBAC
configure-harbor-rbac $registry_url $project_id $policy.users $auth
# Configure webhooks
if ($policy.webhooks | length) > 0 {
configure-harbor-webhooks $registry_url $project_id $policy.webhooks $auth
}
print $" ✓ Policies configured"
print ""
}
}
def get-harbor-project-id [
registry_url: string
project_name: string
auth: string
] -> int {
let result = (do {
http get $"http://($registry_url)/api/v2.0/projects?name=($project_name)" --headers {
"Authorization": $"Basic ($auth)"
}
} | complete)
if $result.exit_code == 0 {
let projects = ($result.stdout | from json)
if ($projects | length) > 0 {
return ($projects | first | get project_id)
}
}
return null
}
def configure-harbor-rbac [
registry_url: string
project_id: int
users: list
auth: string
] {
print " Configuring RBAC..."
for user in $users {
let role_id = match $user.role {
"admin" => 1
"developer" => 2
"guest" => 3
_ => 2
}
let member_body = {
role_id: $role_id
member_user: {
username: $user.name
}
}
let result = (do {
http post $"http://($registry_url)/api/v2.0/projects/($project_id)/members" $member_body --headers {
"Authorization": $"Basic ($auth)"
"Content-Type": "application/json"
}
} | complete)
if $result.exit_code == 0 {
print $" ✓ User ($user.name) added as ($user.role)"
} else {
if ($result.stderr | str contains "already exists") {
print $" User ($user.name) already exists"
} else {
print $" ⚠ Error adding user ($user.name)"
}
}
}
}
def configure-harbor-webhooks [
registry_url: string
project_id: int
webhooks: list
auth: string
] {
print " Configuring webhooks..."
for webhook in $webhooks {
let webhook_body = {
name: $"webhook-($webhook.event)"
description: $"Webhook for ($webhook.event) events"
enabled: true
event_types: [$webhook.event]
targets: [
{
type: "http"
address: $webhook.url
skip_cert_verify: true
}
]
}
let result = (do {
http post $"http://($registry_url)/api/v2.0/projects/($project_id)/webhook/policies" $webhook_body --headers {
"Authorization": $"Basic ($auth)"
"Content-Type": "application/json"
}
} | complete)
if $result.exit_code == 0 {
print $" ✓ Webhook for ($webhook.event) configured"
} else {
print $" ⚠ Error configuring webhook for ($webhook.event)"
}
}
}
def configure-distribution-policies [registry_url: string, policies: list] {
print "Configuring Distribution policies...\n"
print " Distribution uses htpasswd for authentication"
print " Generating htpasswd file...\n"
# Collect all unique users
let all_users = ($policies | each { |p| $p.users } | flatten | get name | uniq)
print "Users to create:"
for user in $all_users {
print $" - ($user)"
}
print "\n To create users, run:"
print " htpasswd -Bc htpasswd <username>"
print "\n Access control is enforced at the authentication layer"
print " All authenticated users can push/pull"
print " Anonymous users can only pull if allowed in config.yml"
}
# Helper: Show policy for namespace
export def "policy show" [
namespace: string
] {
let policies = get-policy-definitions
let policy = ($policies | where namespace == $namespace | first)
if ($policy | is-empty) {
print $"Policy for namespace ($namespace) not found"
return
}
print $"Policy for: ($policy.namespace)\n"
print "Access Control:"
print " Authenticated users:"
print $" Read: ($policy.access.authenticated.read)"
print $" Write: ($policy.access.authenticated.write)"
print $" Delete: ($policy.access.authenticated.delete)"
print " Anonymous users:"
print $" Read: ($policy.access.anonymous.read)"
print $" Write: ($policy.access.anonymous.write)"
print $" Delete: ($policy.access.anonymous.delete)"
print "\nUsers:"
for user in $policy.users {
print $" - ($user.name) (($user.role))"
}
if ($policy.webhooks | length) > 0 {
print "\nWebhooks:"
for webhook in $policy.webhooks {
print $" - Event: ($webhook.event)"
print $" URL: ($webhook.url)"
}
}
}
# Helper: List all policies
export def "policy list" [] -> table {
let policies = get-policy-definitions
$policies | each { |p|
{
namespace: $p.namespace
auth_read: $p.access.authenticated.read
auth_write: $p.access.authenticated.write
anon_read: $p.access.anonymous.read
users: ($p.users | length)
webhooks: ($p.webhooks | length)
}
}
}