mirror of
https://github.com/minio/minio.git
synced 2025-03-31 17:53:43 -04:00
support LDAP service accounts via SFTP, FTP logins (#18599)
This commit is contained in:
parent
e99a597899
commit
4bc5ed6c76
@ -248,12 +248,19 @@ func (driver *ftpDriver) CheckPasswd(c *ftp.Context, username, password string)
|
|||||||
defer stopFn(err)
|
defer stopFn(err)
|
||||||
|
|
||||||
if globalIAMSys.LDAPConfig.Enabled() {
|
if globalIAMSys.LDAPConfig.Enabled() {
|
||||||
ldapUserDN, groupDistNames, err := globalIAMSys.LDAPConfig.Bind(username, password)
|
sa, _, err := globalIAMSys.getServiceAccount(context.Background(), username)
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
ldapPolicies, _ := globalIAMSys.PolicyDBGet(ldapUserDN, groupDistNames...)
|
if errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return len(ldapPolicies) > 0, nil
|
ldapUserDN, groupDistNames, err := globalIAMSys.LDAPConfig.Bind(username, password)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ldapPolicies, _ := globalIAMSys.PolicyDBGet(ldapUserDN, groupDistNames...)
|
||||||
|
return len(ldapPolicies) > 0, nil
|
||||||
|
}
|
||||||
|
return subtle.ConstantTimeCompare([]byte(sa.Credentials.SecretKey), []byte(password)) == 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ui, ok := globalIAMSys.GetUser(context.Background(), username)
|
ui, ok := globalIAMSys.GetUser(context.Background(), username)
|
||||||
@ -269,58 +276,70 @@ func (driver *ftpDriver) getMinIOClient(ctx *ftp.Context) (*minio.Client, error)
|
|||||||
return nil, errNoSuchUser
|
return nil, errNoSuchUser
|
||||||
}
|
}
|
||||||
if !ok && globalIAMSys.LDAPConfig.Enabled() {
|
if !ok && globalIAMSys.LDAPConfig.Enabled() {
|
||||||
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.LookupUserDN(ctx.Sess.LoginUser())
|
sa, _, err := globalIAMSys.getServiceAccount(context.Background(), ctx.Sess.LoginUser())
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, targetGroups...)
|
|
||||||
if len(ldapPolicies) == 0 {
|
|
||||||
return nil, errAuthentication
|
|
||||||
}
|
|
||||||
expiryDur, err := globalIAMSys.LDAPConfig.GetExpiryDuration("")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
claims := make(map[string]interface{})
|
|
||||||
claims[expClaim] = UTCNow().Add(expiryDur).Unix()
|
|
||||||
claims[ldapUser] = targetUser
|
|
||||||
claims[ldapUserN] = ctx.Sess.LoginUser()
|
|
||||||
|
|
||||||
cred, err := auth.GetNewCredentialsWithMetadata(claims, globalActiveCred.SecretKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the parent of the temporary access key, this is useful
|
var mcreds *credentials.Credentials
|
||||||
// in obtaining service accounts by this cred.
|
if errors.Is(err, errNoSuchServiceAccount) {
|
||||||
cred.ParentUser = targetUser
|
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.LookupUserDN(ctx.Sess.LoginUser())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, targetGroups...)
|
||||||
|
if len(ldapPolicies) == 0 {
|
||||||
|
return nil, errAuthentication
|
||||||
|
}
|
||||||
|
expiryDur, err := globalIAMSys.LDAPConfig.GetExpiryDuration("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
claims := make(map[string]interface{})
|
||||||
|
claims[expClaim] = UTCNow().Add(expiryDur).Unix()
|
||||||
|
claims[ldapUser] = targetUser
|
||||||
|
claims[ldapUserN] = ctx.Sess.LoginUser()
|
||||||
|
|
||||||
// Set this value to LDAP groups, LDAP user can be part
|
cred, err := auth.GetNewCredentialsWithMetadata(claims, globalActiveCred.SecretKey)
|
||||||
// of large number of groups
|
if err != nil {
|
||||||
cred.Groups = targetGroups
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Set the newly generated credentials, policyName is empty on purpose
|
// Set the parent of the temporary access key, this is useful
|
||||||
// LDAP policies are applied automatically using their ldapUser, ldapGroups
|
// in obtaining service accounts by this cred.
|
||||||
// mapping.
|
cred.ParentUser = targetUser
|
||||||
updatedAt, err := globalIAMSys.SetTempUser(context.Background(), cred.AccessKey, cred, "")
|
|
||||||
if err != nil {
|
// Set this value to LDAP groups, LDAP user can be part
|
||||||
return nil, err
|
// of large number of groups
|
||||||
|
cred.Groups = targetGroups
|
||||||
|
|
||||||
|
// Set the newly generated credentials, policyName is empty on purpose
|
||||||
|
// LDAP policies are applied automatically using their ldapUser, ldapGroups
|
||||||
|
// mapping.
|
||||||
|
updatedAt, err := globalIAMSys.SetTempUser(context.Background(), cred.AccessKey, cred, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call hook for site replication.
|
||||||
|
logger.LogIf(context.Background(), globalSiteReplicationSys.IAMChangeHook(context.Background(), madmin.SRIAMItem{
|
||||||
|
Type: madmin.SRIAMItemSTSAcc,
|
||||||
|
STSCredential: &madmin.SRSTSCredential{
|
||||||
|
AccessKey: cred.AccessKey,
|
||||||
|
SecretKey: cred.SecretKey,
|
||||||
|
SessionToken: cred.SessionToken,
|
||||||
|
ParentUser: cred.ParentUser,
|
||||||
|
},
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}))
|
||||||
|
|
||||||
|
mcreds = credentials.NewStaticV4(cred.AccessKey, cred.SecretKey, cred.SessionToken)
|
||||||
|
} else {
|
||||||
|
mcreds = credentials.NewStaticV4(sa.Credentials.AccessKey, sa.Credentials.SecretKey, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call hook for site replication.
|
|
||||||
logger.LogIf(context.Background(), globalSiteReplicationSys.IAMChangeHook(context.Background(), madmin.SRIAMItem{
|
|
||||||
Type: madmin.SRIAMItemSTSAcc,
|
|
||||||
STSCredential: &madmin.SRSTSCredential{
|
|
||||||
AccessKey: cred.AccessKey,
|
|
||||||
SecretKey: cred.SecretKey,
|
|
||||||
SessionToken: cred.SessionToken,
|
|
||||||
ParentUser: cred.ParentUser,
|
|
||||||
},
|
|
||||||
UpdatedAt: updatedAt,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return minio.New(driver.endpoint, &minio.Options{
|
return minio.New(driver.endpoint, &minio.Options{
|
||||||
Creds: credentials.NewStaticV4(cred.AccessKey, cred.SecretKey, cred.SessionToken),
|
Creds: mcreds,
|
||||||
Secure: globalIsTLS,
|
Secure: globalIsTLS,
|
||||||
Transport: globalRemoteFTPClientTransport,
|
Transport: globalRemoteFTPClientTransport,
|
||||||
})
|
})
|
||||||
|
@ -93,55 +93,66 @@ func (f *sftpDriver) getMinIOClient() (*minio.Client, error) {
|
|||||||
return nil, errNoSuchUser
|
return nil, errNoSuchUser
|
||||||
}
|
}
|
||||||
if !ok && globalIAMSys.LDAPConfig.Enabled() {
|
if !ok && globalIAMSys.LDAPConfig.Enabled() {
|
||||||
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.LookupUserDN(f.AccessKey())
|
sa, _, err := globalIAMSys.getServiceAccount(context.Background(), f.AccessKey())
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
expiryDur, err := globalIAMSys.LDAPConfig.GetExpiryDuration("")
|
var mcreds *credentials.Credentials
|
||||||
if err != nil {
|
if errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return nil, err
|
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.LookupUserDN(f.AccessKey())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
expiryDur, err := globalIAMSys.LDAPConfig.GetExpiryDuration("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
claims := make(map[string]interface{})
|
||||||
|
claims[expClaim] = UTCNow().Add(expiryDur).Unix()
|
||||||
|
for k, v := range f.permissions.CriticalOptions {
|
||||||
|
claims[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
cred, err := auth.GetNewCredentialsWithMetadata(claims, globalActiveCred.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the parent of the temporary access key, this is useful
|
||||||
|
// in obtaining service accounts by this cred.
|
||||||
|
cred.ParentUser = targetUser
|
||||||
|
|
||||||
|
// Set this value to LDAP groups, LDAP user can be part
|
||||||
|
// of large number of groups
|
||||||
|
cred.Groups = targetGroups
|
||||||
|
|
||||||
|
// Set the newly generated credentials, policyName is empty on purpose
|
||||||
|
// LDAP policies are applied automatically using their ldapUser, ldapGroups
|
||||||
|
// mapping.
|
||||||
|
updatedAt, err := globalIAMSys.SetTempUser(context.Background(), cred.AccessKey, cred, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call hook for site replication.
|
||||||
|
logger.LogIf(context.Background(), globalSiteReplicationSys.IAMChangeHook(context.Background(), madmin.SRIAMItem{
|
||||||
|
Type: madmin.SRIAMItemSTSAcc,
|
||||||
|
STSCredential: &madmin.SRSTSCredential{
|
||||||
|
AccessKey: cred.AccessKey,
|
||||||
|
SecretKey: cred.SecretKey,
|
||||||
|
SessionToken: cred.SessionToken,
|
||||||
|
ParentUser: cred.ParentUser,
|
||||||
|
},
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}))
|
||||||
|
|
||||||
|
mcreds = credentials.NewStaticV4(cred.AccessKey, cred.SecretKey, cred.SessionToken)
|
||||||
|
} else {
|
||||||
|
mcreds = credentials.NewStaticV4(sa.Credentials.AccessKey, sa.Credentials.SecretKey, "")
|
||||||
}
|
}
|
||||||
claims := make(map[string]interface{})
|
|
||||||
claims[expClaim] = UTCNow().Add(expiryDur).Unix()
|
|
||||||
for k, v := range f.permissions.CriticalOptions {
|
|
||||||
claims[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
cred, err := auth.GetNewCredentialsWithMetadata(claims, globalActiveCred.SecretKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the parent of the temporary access key, this is useful
|
|
||||||
// in obtaining service accounts by this cred.
|
|
||||||
cred.ParentUser = targetUser
|
|
||||||
|
|
||||||
// Set this value to LDAP groups, LDAP user can be part
|
|
||||||
// of large number of groups
|
|
||||||
cred.Groups = targetGroups
|
|
||||||
|
|
||||||
// Set the newly generated credentials, policyName is empty on purpose
|
|
||||||
// LDAP policies are applied automatically using their ldapUser, ldapGroups
|
|
||||||
// mapping.
|
|
||||||
updatedAt, err := globalIAMSys.SetTempUser(context.Background(), cred.AccessKey, cred, "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call hook for site replication.
|
|
||||||
logger.LogIf(context.Background(), globalSiteReplicationSys.IAMChangeHook(context.Background(), madmin.SRIAMItem{
|
|
||||||
Type: madmin.SRIAMItemSTSAcc,
|
|
||||||
STSCredential: &madmin.SRSTSCredential{
|
|
||||||
AccessKey: cred.AccessKey,
|
|
||||||
SecretKey: cred.SecretKey,
|
|
||||||
SessionToken: cred.SessionToken,
|
|
||||||
ParentUser: cred.ParentUser,
|
|
||||||
},
|
|
||||||
UpdatedAt: updatedAt,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return minio.New(f.endpoint, &minio.Options{
|
return minio.New(f.endpoint, &minio.Options{
|
||||||
Creds: credentials.NewStaticV4(cred.AccessKey, cred.SecretKey, cred.SessionToken),
|
Creds: mcreds,
|
||||||
Secure: globalIsTLS,
|
Secure: globalIsTLS,
|
||||||
Transport: globalRemoteFTPClientTransport,
|
Transport: globalRemoteFTPClientTransport,
|
||||||
})
|
})
|
||||||
|
@ -20,6 +20,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -110,21 +111,36 @@ func startSFTPServer(c *cli.Context) {
|
|||||||
sshConfig := &ssh.ServerConfig{
|
sshConfig := &ssh.ServerConfig{
|
||||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||||||
if globalIAMSys.LDAPConfig.Enabled() {
|
if globalIAMSys.LDAPConfig.Enabled() {
|
||||||
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.Bind(c.User(), string(pass))
|
sa, _, err := globalIAMSys.getServiceAccount(context.Background(), c.User())
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, errNoSuchServiceAccount) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, targetGroups...)
|
if errors.Is(err, errNoSuchServiceAccount) {
|
||||||
if len(ldapPolicies) == 0 {
|
targetUser, targetGroups, err := globalIAMSys.LDAPConfig.Bind(c.User(), string(pass))
|
||||||
return nil, errAuthentication
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, targetGroups...)
|
||||||
|
if len(ldapPolicies) == 0 {
|
||||||
|
return nil, errAuthentication
|
||||||
|
}
|
||||||
|
return &ssh.Permissions{
|
||||||
|
CriticalOptions: map[string]string{
|
||||||
|
ldapUser: targetUser,
|
||||||
|
ldapUserN: c.User(),
|
||||||
|
},
|
||||||
|
Extensions: make(map[string]string),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
return &ssh.Permissions{
|
if subtle.ConstantTimeCompare([]byte(sa.Credentials.SecretKey), pass) == 1 {
|
||||||
CriticalOptions: map[string]string{
|
return &ssh.Permissions{
|
||||||
ldapUser: targetUser,
|
CriticalOptions: map[string]string{
|
||||||
ldapUserN: c.User(),
|
"accessKey": c.User(),
|
||||||
},
|
},
|
||||||
Extensions: make(map[string]string),
|
Extensions: make(map[string]string),
|
||||||
}, nil
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, errAuthentication
|
||||||
}
|
}
|
||||||
|
|
||||||
ui, ok := globalIAMSys.GetUser(context.Background(), c.User())
|
ui, ok := globalIAMSys.GetUser(context.Background(), c.User())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user