prvng_platform/oci-registry/scripts/configure-policies.nu

368 lines
10 KiB
Plaintext
Raw Normal View History

2025-10-07 10:59:52 +01:00
#!/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)
}
}
}