# Cloud identity, IAM and RBAC

Harbor Desk now runs in the cloud. Separate human, pipeline and workload identities, and demonstrate least privilege without confusing sign-in with resource authority.

Original AI-assisted SecNet educational content. Fictional local examples; not a standards provider publication, endorsement or compliance evidence. Page exercises do not create account progress.

Sources checked: 2026-10-21

## Responsibility and identity boundaries

Using a managed service does not delegate application data authorization to the provider. Assign separate responsibility for resources, identity issuance, policy and evidence. Use strong authentication and controlled emergency access for people, and short-lived scoped identities for workloads. Sharing one administrator key across development, deployment and runtime expands incident impact. Real provider roles are not identical to the abstract permissions used in this exercise.

## Federation acceptance conditions

A signed token is not necessarily the intended workload. Verify expected issuer, audience, subject and lifetime, and bind trust to a specific repository, branch or environment. Include a fork job trying to gain production deployment identity as a negative case. signatureValid represents an evidence assumption here; the browser does not verify signatures or contact an identity provider. Test new federation rules narrowly using observed allowed and denied requests.

## Indirect authority through RBAC

A namespaced role is not inherently low risk. Examine how bind, escalate, impersonate and secret-reading privileges can yield other authority. Pod creation may also affect workload identity and mountable secrets. Select only required objects and actions for the Harbor reader, and map the full role/binding chain in production. Negative tests should include wrong tenant and wrong action. Do not infer effective authority from a role named reader.

## Worked example: the north reader

The north reader may read its own tenant’s ticket; a south record and delete-backup action are denied. Record all three outcomes using the same test identity. Next, change only audience or subject in the federation scenario to isolate the trust condition. Actual evidence needs identity origin, role/binding revision, resource scope, denial response and an owner for approved exceptions. Passing the model does not establish that these records exist. An auditor should connect policy text with effective authority and observed outcomes.

## Working sequence

1. Inventory human and workload identities.
2. Define resource, action and tenant scope.
3. Constrain federation trust conditions.
4. Review indirect RBAC escalation.
5. Record allowed/denied evidence and exception ownership.

## 1. Sign-in or authority?

signedIn is only an identity signal. Require the same tenant and read-ticket scope separately; wrong action and tenant are denied. This model is not a complete cloud IAM engine.

This code is a local policy model; it does not replace target/cluster testing.

### Weak implementation
```js
s=>s.signedIn
```

### Corrected implementation
```js
s=>s.signedIn&&s.action==='read-ticket'&&s.actorTenant===s.resourceTenant
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "same-tenant",
      "input": {
        "signedIn": true,
        "action": "read-ticket",
        "actorTenant": "north",
        "resourceTenant": "north"
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "foreign-tenant",
      "input": {
        "signedIn": true,
        "action": "read-ticket",
        "actorTenant": "south",
        "resourceTenant": "north"
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "unapproved-action",
      "input": {
        "signedIn": true,
        "action": "delete-backup",
        "actorTenant": "north",
        "resourceTenant": "north"
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "same-tenant",
      "input": {
        "signedIn": true,
        "action": "read-ticket",
        "actorTenant": "north",
        "resourceTenant": "north"
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "foreign-tenant",
      "input": {
        "signedIn": true,
        "action": "read-ticket",
        "actorTenant": "south",
        "resourceTenant": "north"
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "unapproved-action",
      "input": {
        "signedIn": true,
        "action": "delete-backup",
        "actorTenant": "north",
        "resourceTenant": "north"
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 2. The intended workload

A valid signature cannot correct a wrong audience, subject or expiry. signatureValid is a verification assumption, not executed cryptography. Missing any required trust condition prevents acceptance.

This code is a local policy model; it does not replace target/cluster testing.

### Weak implementation
```js
s=>s.signatureValid
```

### Corrected implementation
```js
s=>s.signatureValid&&s.issuer==='https://identity.example'&&s.audience==='harbor-api'&&s.subject==='pipeline/main'&&s.unexpired
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "trusted-subject",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/main",
        "unexpired": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "wrong-audience",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "other-api",
        "subject": "pipeline/main",
        "unexpired": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "untrusted-subject",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/fork",
        "unexpired": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "expired",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/main",
        "unexpired": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "trusted-subject",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/main",
        "unexpired": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "wrong-audience",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "other-api",
        "subject": "pipeline/main",
        "unexpired": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "untrusted-subject",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/fork",
        "unexpired": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "expired",
      "input": {
        "signatureValid": true,
        "issuer": "https://identity.example",
        "audience": "harbor-api",
        "subject": "pipeline/main",
        "unexpired": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 3. A role that appears narrow

Namespace scope does not automatically make a role safe. Binding or secret-reading authority is outside this reader profile; separately review the actual effective-authority chain.

This code is a local policy model; it does not replace target/cluster testing.

### Weak implementation
```js
s=>s.namespacedRole
```

### Corrected implementation
```js
s=>s.namespacedRole&&!s.canBind&&!s.canEscalate&&!s.canImpersonate&&!s.canReadSecrets
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "bounded-reader",
      "input": {
        "namespacedRole": true,
        "canBind": false,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": false
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "binding-privilege",
      "input": {
        "namespacedRole": true,
        "canBind": true,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "secret-reader",
      "input": {
        "namespacedRole": true,
        "canBind": false,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "bounded-reader",
      "input": {
        "namespacedRole": true,
        "canBind": false,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": false
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "binding-privilege",
      "input": {
        "namespacedRole": true,
        "canBind": true,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "secret-reader",
      "input": {
        "namespacedRole": true,
        "canBind": false,
        "canEscalate": false,
        "canImpersonate": false,
        "canReadSecrets": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## Exit evidence

- Effective IAM/RBAC chain and identity origin
- Wrong-audience, tenant and action denial tests

## References

- [Google Cloud · Workload Identity Federation practices](https://docs.cloud.google.com/iam/docs/best-practices-for-using-workload-identity-federation)
- [Kubernetes · RBAC good practices](https://kubernetes.io/docs/concepts/security/rbac-good-practices/)
