MinIO Study 3주차 PBAC, LDAP
가시다님이 운영하시는 MinIO Study 3주차 내용을 정리한 게시글 입니다.
1. 실습 환경 구성
이번 실습에서는 리소스를 많이 사용하지 않아 Kind를 아용하여 실습환경을 구성합니다.
kind create cluster --name myk8s --image kindest/node:v1.33.4 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
EOF
helm install --namespace minio-operator --create-namespace minio-operator minio-operator/operator --set operator.replicaCount=1
cat << EOF > minio-tenant-1-values.yaml
tenant:
name: tenant1
configSecret:
name: tenant1-env-configuration
accessKey: minio
secretKey: minio123
pools:
- servers: 1
name: pool-0
volumesPerServer: 4
size: 1Gi
storageClassName: standard
env:
- name: MINIO_STORAGE_CLASS_STANDARD
value: "EC:1"
- name: MINIO_PROMETHEUS_AUTH_TYPE
value: public
features:
bucketDNS: true
metrics:
enabled: true
port: 9000
protocol: http
EOF
helm install --namespace tenant1 --create-namespace --values minio-tenant-1-values.yaml tenant1 minio-operator/tenant
# 접속을 위한 Node Port 적용
kubectl patch svc -n tenant1 tenant1-console -p '{"spec": {"type": "NodePort", "ports": [{"port": 9443, "targetPort": 9443, "nodePort": 30001}]}}'
kubectl patch svc -n tenant1 minio -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 9000, "nodePort": 30002}]}}'
# 기본키(minio , minio123)
wslview "https://127.0.0.1:30001"
# mc alias
mc alias set k8s-tenant1 https://127.0.0.1:30002 minio minio123 --insecure
mc alias list
# alias
MYALIAS=k8s-tenant1
# 버킷 생성
mc mb $MYALIAS/mybucket --insecure
mc ls $MYALIAS --insecure
# object 업로드
echo hello > hello.txt
mc cp hello.txt $MYALIAS/mybucket --insecure2. MinIO에서 PBAC 및 인증, 인가
인증 및 인가 관리
인증이란 연결 시 클라이언트의 신원을 확인하는 행위를 말하며, MinIO에서는 클라이언트가 인증을 수행할 때 AWS Signature Version 4 프로토콜의 PUT 방식을 사용하여 인증합니다.
클라이언트는 인증 시 Access Key와 Secret Key를 사용하여 인증을 해야합니다.
인가는 인증된 클라이언트가 수행할 수 있는 작업 및 리소스를 제한 하는 행위를 말하며, MinIO에서는 PBAC(Policy-based access control)을 사용하여 인증된 사용자 및 사용자 그룹의 행위를 관리합니다.
MinIO는 기본적으로 내장된 IDP(ID Provider)가 존재하지만 OpenID, LDAP과 같은 외부 IDP를 사용하여 ID를 관리할 수 있습니다.
외부 IDP를 사용하게 되면 MinIO 내부 IDP가 비활상화가 됩니다.
접근 관리
MinIO는 외부 IDP를 사용해도, 접근 정책을 MinIO가 관리를 합니다.
MinIO는 기본적으로 연결되거나 상속된 정책에서 명시적으로 허용하지 않은 직업이나 리소스에 대해 액세스를 거부합니다. 할당 및 상속된 정채기 없는 사용자인 경우 기본적으로 MinIO 관리 API를 사용할 수 없습니다.
MinIO PBAC는 AWS IAM 정책 구문, 구조 및 동작과 호환이 되도록 설계 되어있습니다.
MinIO IDP
기본적으로 내장되어있는 MinIO IDP에서는 고유한 Access Key나 비밀번호를 사용하여 클라이언트가 인증할 수 있도록 제공합니다.
Access Key를 사용하는 경우 Key에 만료 기간을 적용 하여 기간별로 Access Key를 적용할 수 있습니다.
MinIO 최초 설치 시 ID관리자(root)는 모든 작업 및 리소스에 액세스 할 수 있는 계정이 생성됩니다. 이때 MINIO_ROOT_USER, MINIO_ROOT_PASSWRD 환경변수 값으로 생성됩니다.
Access Key
MinIO의 Access Key는 인증된 MinIO 사용자의 ID 이며 외부에서 관리되는 ID도 포함됩니다.
각 Access Key는 부모 사용자 또는 부모 사용자의 그룹에 연결된 정책에 따라 권한을 적용 받습니다.
Access Key는 부모 사용자 및 그룹의 정책에서 추가적으로 제한할 수 있는 선택적 인라인 정책도 지원합니다.
PBAC
MinIO에서 제공하는 기본적인 내장 정책은 다음과 같습니다.
consoleAdmin
- MinIO의 모든 리소스에 대한 S3 및 관리 API 작업들에 대한 완전한 Access 권한을 부여합니다.
s3:*
admin:*readonly
- MinIO의 모든 객체에 대한 읽기 전용 권한을 부여합니다.
s3:GetBucketLocation
s3:GetObjectreadwrite
- MinIO의 모든 버킷과 객체에 대한 읽기 및 쓰기 권한을 부여합니다.
s3:*diagnostics
- MinIO 배포에 대한 진단 작업을 수행할 수 있는 권한을 부여합니다.
admin:ServerTrace
admin:Profiling
admin:ConsoleLog
admin:ServerInfo
admin:TopLocksInfo
admin:OBDInfo
admin:BandwidthMonitor
admin:PrometheusMinIO 정책 문서는 AWS IAM 정책 문서와 동일한 스키마를 사용하며 예시는 다음과 같습니다.
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [ "s3:<ActionName>", ... ],
"Resource" : "arn:aws:s3:::*",
"Condition" : { ... }
},
{
"Effect" : "Deny",
"Action" : [ "s3:<ActionName>", ... ],
"Resource" : "arn:aws:s3:::*",
"Condition" : { ... }
}
]
}PBAC 정책 실습
MYALIAS=k8s-tenant1
mc ls $MYALIAS --insecure
# 내장 정첵 확인
mc admin policy list $MYALIAS --insecure
# writeonly
# consoleAdmin
# diagnostics
# readonly
# readwrite
# readonly 정책 확인
mc admin policy info $MYALIAS readonly --insecure | jq
# {
# "PolicyName": "readonly",
# "Policy": {
# "Version": "2012-10-17",
# "Statement": [
# {
# "Effect": "Allow",
# "Action": [
# "s3:GetBucketLocation",
# "s3:GetObject"
# ],
# "Resource": [
# "arn:aws:s3:::*"
# ]
# }
# ]
# }
# }
# 기본 정책을 정책 부분만 파일로 저장
mc admin policy info $MYALIAS readonly --insecure --policy-file new.json
# Action 추가
vi new.json
.....
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:List*"
],
.....
# 정책 생성
mc admin policy create $MYALIAS readlist new.json --insecure
# Created policy `readlist` successfully.
# 생성된 정책 확인
mc admin policy list $MYALIAS --insecure
# readwrite
# writeonly
# consoleAdmin
# diagnostics
# readlist
# readonly
mc admin policy info $MYALIAS readlist --insecure | jq
# {
# "PolicyName": "readlist",
# "Policy": {
# "Version": "2012-10-17",
# "Statement": [
# {
# "Effect": "Allow",
# "Action": [
# "s3:GetBucketLocation",
# "s3:GetObject",
# "s3:List*"
# ],
# "Resource": [
# "arn:aws:s3:::*"
# ]
# }
# ]
# },
# "CreateDate": "2025-09-27T13:12:50.764Z",
# "UpdateDate": "2025-09-27T13:12:50.764Z"
# }
# 정책 제거 실습
mc admin policy remove $MYALIAS diagnostics --insecure
# 내장 정책은 삭제 불가
# mc: <ERROR> Unable to remove policy. We encountered an internal error, please try again. (inbuilt policy `diagnostics` not allowed to be deleted).
mc admin policy remove $MYALIAS readlist --insecure
# Removed policy `readlist` successfully.
Figure 2.1 생성된 Policy 확인
User 생성 후 Policy 적용 실습
# user 없음 확인
mc admin user list $MYALIAS --insecure
# user1 생성 : 시크릿키 mypassword
mc admin user add $MYALIAS user1 mypassword --insecure
# Added user `user1` successfully.
mc admin user list $MYALIAS --insecure
# enabled user1
# User에 정책 할당
mc admin policy attach $MYALIAS readwrite --user user1 --insecure
# Attached Policies: [readwrite]
# To User: user1
# 정책 매핑된 Entity 출력
mc admin policy entities $MYALIAS --policy readwrite --insecure
# Query time: 2025-09-27T13:40:24Z
# Policy -> Entity Mappings:
# Policy: readwrite
# User Mappings:
# user1

Figure 2.2 신규 유저 Policy 확인

Figure 2.3 변경된 Policy 확인
Group 사용 실습
# 그룹 생성
mc admin group add $MYALIAS devteam user1 --insecure
# 그룹에 정책 적용
mc admin policy attach $MYALIAS readonly --group devteam --insecure
# Attached Policies: [readonly]
# To Group: devteam
mc admin group info $MYALIAS devteam --insecure
# Group: devteam
# Status: enabled
# Policy: readonly
# Members: user1
# 신규 정책 적용
cat << EOF > s3-list.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
EOF
# lister 정책 생성
mc admin policy create $MYALIAS lister s3-list.json --insecure
# Created policy `lister` successfully.
# devteam 그룹에 추가 부착
mc admin policy attach $MYALIAS lister --group devteam --insecure
# Attached Policies: [lister]
# To Group: devteam
3. LDAP
✅ LDAP
Lightweight Directory Access Protocol의 약자이며, 디렉터리 서비스(계층형 데이터 저장소)에 대한 질의/수정/인증을 수행하는 애플리케이션 레벨 프로토콜입니다.
사용자·그룹·권한 정보를 계층적으로 보관하는 주소록/조직도의 개념입니다.

Figure 3.1 LDAP Flow 예시
OpenLDAP 배포
MinIO와 LDAP을 연결하기 위해 OpenLDAP을 설치하도록 하겠습니다.
구성하고 있는 LDAP의 그림은 다음과 같습니다.
dc=minio,dc=io
├── cn=developer (사용자)
├── cn=maintainer (사용자)
├── cn=admin_root (사용자)
├── ou=Users (OU)
└── ou=Groups
├── cn=Admins (groupOfUniqueNames, member=admin_root)
└── cn=Maintainers (groupOfUniqueNames, member=maintainer,developer)# OpenLDAP Configmap
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: openldap-admin-secret
type: Opaque
stringData:
admin-password: "admin123"
EOF
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: openldap-bootstrap
namespace: default
data:
bootstrap.ldif: |
dn: cn=developer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: developer
givenname: developer
sn: Developer
displayname: Developer User
mail: developer@minio.io
userpassword: developer_pass
dn: cn=maintainer,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: maintainer
givenname: maintainer
sn: Maintainer
displayname: Maintainer User
mail: maintainer@minio.io
userpassword: maintainer_pass
dn: cn=admin_root,dc=minio,dc=io
changetype: add
objectclass: inetOrgPerson
cn: admin_root
givenname: admin_root
sn: AdminRoot
displayname: Admin User
mail: admin_root@minio.io
userpassword: admin_pass
dn: ou=Groups,dc=minio,dc=io
changetype: add
objectclass: organizationalUnit
ou: Groups
dn: ou=Users,dc=minio,dc=io
changetype: add
objectclass: organizationalUnit
ou: Users
dn: cn=Admins,ou=Groups,dc=minio,dc=io
changetype: add
cn: Admins
objectclass: groupOfUniqueNames
uniqueMember: cn=admin_root,dc=minio,dc=io
dn: cn=Maintainers,ou=Groups,dc=minio,dc=io
changetype: add
cn: Maintainers
objectclass: groupOfUniqueNames
uniqueMember: cn=maintainer,dc=minio,dc=io
uniqueMember: cn=developer,dc=minio,dc=io
EOF
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: openldap
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: openldap
template:
metadata:
labels:
app: openldap
spec:
initContainers:
- name: copy-bootstrap
image: busybox
command: ['sh', '-c', 'cp /config/bootstrap.ldif /ldif/bootstrap.ldif']
volumeMounts:
- name: configmap-ldif
mountPath: /config
- name: writable-ldif
mountPath: /ldif
containers:
- name: openldap
image: osixia/openldap:1.5.0
env:
- name: LDAP_ORGANISATION
value: "MinIO"
- name: LDAP_DOMAIN
value: "minio.io"
- name: LDAP_ADMIN_PASSWORD
value: "admin123"
- name: LDAP_REMOVE_CONFIG_AFTER_SETUP
value: "false"
ports:
- containerPort: 389
- containerPort: 636
volumeMounts:
- name: writable-ldif
mountPath: /container/service/slapd/assets/config/bootstrap/ldif/custom
volumes:
- name: configmap-ldif
configMap:
name: openldap-bootstrap
- name: writable-ldif
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: openldap
namespace: default
spec:
selector:
app: openldap
ports:
- name: ldap
port: 389
targetPort: 389
- name: ldaps
port: 636
targetPort: 636
- name: http
port: 80
targetPort: 80
EOF
# 관리자 DN(암호)로 ldapsearch 확인
kubectl exec -it deploy/openldap -c openldap -- \
ldapsearch -x -H ldap://localhost -D "cn=admin,dc=minio,dc=io" -w admin123 -b "dc=minio,dc=io"MinIO에서 AD/LDAP Access 관리
외부 AD/LDAP 공급자가 관리하는 ID는 MinIO에서 사용자의 고유 이름을 사용하며, 기존 정책에 매핑을 하려고 시도합니다.
MinIO는 LDAP 정책을 적용하는 것이 아닌 MinIO에 있는 내부 정책을 적용합니다.
MinIO가 AD/LDAP 자격 증명을 사용하는 Application의 로그인 흐름은 다음과 같습니다.
- MinIO 보안 토큰 서비스(STS) API EndPoint에 AD/LDAP 자격 증명을 저장
- MinIO는 제공된 자격 증명을 AD/LDAP 서버와 비교
- MinIO는 사용자 고유 이름(DN)과 일치하는 정책 확인 후 해당 정책을 인증된 사용자에게 할당
- MinIO는 STS API응답에서 Access Key, Secret Key, 토큰 형태로 임시 자격 증명을 반환
MinIO 에 LDAP 연동
Admin 계정으로 로그인하여 왼쪽 패널의 LDAP에서 다음과 같이 설정합니다.
- Server Insecure :
Enabled - Server Address :
openldap.default.svc.cluster.local:389 - Lookup Bind DN* : `cn=admin,dc=minio,dc=io`
- Lookup Bind Password* :
admin123 - User DN Search Base* : `dc=minio,dc=io`**
- User DN Search Filter* :
(cn=%s)

Figure 3.2 LDAP 설정
적용 시 Restart 수행 메시지가 발생하는데, 이때 Restart를 수행 후 새로고침을 하면 LDAP 연동이 된 것을 확인 할 수 있습니다.
연동 되면 Identity에 User,Group이 사라져 있는 것을 확인 할 수 있습니다.

Figure 3.3 LDAP 적용 확인
# LDAP 적용 확인
mc idp ldap info $MYALIAS --insecure
# ╭───────────────────────────────────────────────────────────────╮
# │ enable: on │
# │ lookup_bind_dn: cn=admin,dc=minio,dc=io │
# │ server_addr: openldap.default.svc.cluster.local:389 │
# │ server_insecure: on │
# │user_dn_search_base_dn: dc=minio,dc=io │
# │ user_dn_search_filter: (cn=%s) │
# ╰───────────────────────────────────────────────────────────────╯
# 내장 IDP 비활성화 확인
mc admin user list $MYALIAS --insecure
# DN(admin_root) 에 consoleAdmin 정책 할당
mc idp ldap policy attach $MYALIAS consoleAdmin --user='cn=admin_root,dc=minio,dc=io' --insecure
# Attached Policies: [consoleAdmin]
# To User: cn=admin_root,dc=minio,dc=io
# 계정 정보 확인
mc admin user list $MYALIAS --insecure
# enabled cn=admin_root,dc=... consoleAdmin

Figure 3.3 LDAP User Tab에서 확인
사용자, 그룹 매핑은 LDAP에서 수행하지만, 정책은 MinIO에서 관리되는 것을 확인할 수 있습니다.
LDAP 그룹 검색 적용
mc idp ldap update $MYALIAS \
group_search_filter="(&(objectClass=groupOfUniqueNames)(uniqueMember=%d))" \
group_search_base_dn="dc=minio,dc=io" --insecure
# Successfully applied new settings.
# Please restart your server 'mc admin service restart k8s-tenant1'.
mc admin service restart $MYALIAS --insecure
# Service status: ▱▱▱ [DONE]
# Summary:
# ┌───────────────┬─────────────────────────────┐
# │ Servers: │ 1 online, 0 offline, 0 hung │
# │ Restart Time: │ 609.206846ms │
# └───────────────┴─────────────────────────────┘
mc idp ldap info $MYALIAS --insecure
# ╭─────────────────────────────────────────────────────────────────────────────╮
# │ enable: on │
# │ group_search_base_dn: dc=minio,dc=io │
# │ group_search_filter: (&(objectClass=groupOfUniqueNames)(uniqueMember=%d)) │
# │ lookup_bind_dn: cn=admin,dc=minio,dc=io │
# │ server_addr: openldap.default.svc.cluster.local:389 │
# │ server_insecure: on │
# │user_dn_search_base_dn: dc=minio,dc=io │
# │ user_dn_search_filter: (cn=%s) │
# ╰─────────────────────────────────────────────────────────────────────────────╯
# 그룹 매핑 정책 설정
mc idp ldap policy attach $MYALIAS readwrite \
--group="cn=Maintainers,ou=Groups,dc=minio,dc=io" --insecure
# Attached Policies: [readwrite]
# To Group: cn=Maintainers,ou=Groups,dc=minio,dc=io
# 그룹 매핑 확인
mc admin group list $MYALIAS --insecure
# cn=Maintainers,ou=Groups,dc=minio,dc=io
# devteam
'DevOps > Study' 카테고리의 다른 글
| CI/CD Study 2주차 Helm (0) | 2025.10.26 |
|---|---|
| CI/CD Study 1주차 Image Build (0) | 2025.10.19 |
| MinIO Study 2주차 Performance & Warp (0) | 2025.09.20 |
| MinIO Study 2주차 DirectPV (0) | 2025.09.20 |
| MinIO Study 1주차 MinIO On k8s (0) | 2025.09.13 |