Management SDKs¶
Go and Python clients for IOLake's management API: everything under
/_admin/*, plus STS.
| install | source | |
|---|---|---|
| Go | go get github.com/io-lake/iolake-go-sdk |
iolake-go-sdk |
| Python | pip install iolake-sdk (import iolake) |
iolake-python-sdk |
Both are developed in the main repository under sdk/ and mirrored to their
own repos on every merge. Both are standard library only: no dependencies to
vendor into an operator or a CSI driver. Method names match: Go
CreatePolicy is Python create_policy.
They don't do S3 data operations. Use the S3 SDK you already have (boto3, aws-sdk-go-v2, rclone, mountpoint-s3), pointed at the same endpoint with a credential these mint or obtain.
What they cover¶
- Tenants and tenant admins.
- Users and access keys, including suspend and reactivate, and keys confined to a bucket or prefix.
- IAM policies, groups and roles, attached to users, groups or roles.
- Identity providers: the operator's and each tenant's own OIDC provider.
- STS:
AssumeRoleWithWebIdentityfrom a client that needs no keys. - Block Public Access at bucket, tenant and cluster level, and a bucket's policy status.
- Buckets, bucket policies and dedup.
- One-call provisioning: a bucket plus a key confined to it, with rotation and teardown.
- Cluster operations: pools, nodes, OSD state, rebalance, usage, metrics.
- KMS keys, Iceberg warehouses, and cluster config.
The concepts are explained in Identity and Access and Public Access.
Configure¶
from iolake import Client
admin = Client.from_env() # IOLAKE_ENDPOINT, IOLAKE_ACCESS_KEY(_FILE), IOLAKE_SECRET_KEY(_FILE)
admin, err := iolake.NewFromEnv()
The AWS variable names (AWS_ACCESS_KEY_ID, …) work as fallbacks. In
Kubernetes, prefer the _FILE forms with a mounted Secret. The credential
must be unscoped: a key confined to a bucket is refused on the
management API.
Examples¶
A tenant with its own identity provider, and a role its CI assumes with no stored credential:
from iolake import Client, tenant_oidc_provider_name
acme = Client.from_env() # acme's tenant admin
acme.put_oidc_provider(tenant_oidc_provider_name("acme"), {
"issuer_url": "https://keycloak.acme.example/realms/acme",
"client_id": "iolake", "claim_name": "groups"})
acme.create_policy("data-rw", {"Version": "2012-10-17", "Statement": [{
"Effect": "Allow", "Action": "s3:*",
"Resource": ["arn:aws:s3:::acme-data", "arn:aws:s3:::acme-data/*"]}]})
role = acme.create_role("ci", trust_policy) # see Identity and Access
acme.attach_policy("data-rw", role_name="ci")
# In CI
creds = Client(endpoint=E).assume_role_with_web_identity(role.arn, token, "build-42")
s3 = boto3.client("s3", **creds.boto3_kwargs(E))
Suspend someone now, decide later:
_, err := admin.SuspendUser(ctx, userID) // every key refused; nothing deleted
_, err = admin.ActivateUser(ctx, userID)
A bucket and a key confined to it, for an app:
ba = admin.provision_bucket("app-1", provisioner_user_id=prov_id)
s3 = boto3.client("s3", **ba.boto3_kwargs(E))
Block public access for a whole tenant:
_, err := acme.PutPublicAccessBlock(ctx, "", iolake.BlockAll, nil)
Errors¶
Both surface the HTTP status and, for S3 and STS errors, the error code
(AccessDenied, NoSuchBucket, InvalidIdentityToken, …). Use them to
make calls idempotent:
try:
admin.create_bucket("app-1")
except APIError as e:
if not e.already_exists:
raise
if err := admin.CreateBucket(ctx, "app-1", ""); err != nil && !iolake.IsAlreadyExists(err) {
return err
}
The full reference, with every method, is in each SDK's README.