Minor stylistic changes

This commit is contained in:
Emmanuel BENOîT 2021-02-13 18:26:37 +01:00
parent 50233827b6
commit ceee0bf2f4
3 changed files with 60 additions and 60 deletions

View file

@ -13,11 +13,11 @@ type (
* */ * */
// LDAP server configuration // LDAP server configuration
LdapConfig struct { ldapConfig struct {
Host string Host string `yaml:"host"`
Port uint16 Port uint16 `yaml:"port"`
Tls string TLS string `yaml:"tls"`
TlsNoVerify bool `yaml:"tls_skip_verify"` TLSNoVerify bool `yaml:"tls_skip_verify"`
CaChain string `yaml:"cachain"` CaChain string `yaml:"cachain"`
BindUser string `yaml:"bind_user"` BindUser string `yaml:"bind_user"`
BindPassword string `yaml:"bind_password"` BindPassword string `yaml:"bind_password"`
@ -26,39 +26,39 @@ type (
} }
// Graylog server configuration // Graylog server configuration
GraylogConfig struct { graylogConfig struct {
ApiBase string `yaml:"api_base"` APIBase string `yaml:"api_base"`
Username string Username string
Password string Password string
DeleteAccounts bool `yaml:"delete_accounts"` DeleteAccounts bool `yaml:"delete_accounts"`
} }
// A Graylog object on which privileges are defined // A Graylog object on which privileges are defined
GraylogObject struct { graylogObject struct {
Type string Type string `yaml:"type"`
Id string ID string `yaml:"id"`
Level string Level string `yaml:"level"`
} }
// A mapping from a LDAP group to a set of privileges // A mapping from a LDAP group to a set of privileges
GroupPrivileges struct { groupPrivileges struct {
Roles []string Roles []string
Privileges []GraylogObject Privileges []graylogObject
} }
// All group mappings // All group mappings
GroupMapping map[string]GroupPrivileges groupMapping map[string]groupPrivileges
// The whole configuration // The whole configuration
Configuration struct { configuration struct {
Ldap LdapConfig LDAP ldapConfig
Graylog GraylogConfig Graylog graylogConfig
Mapping GroupMapping Mapping groupMapping
} }
) )
// Check group/privilege mapping configuration // Check group/privilege mapping configuration
func checkPrivMapping(cfg GroupMapping, log *logrus.Entry) { func checkPrivMapping(cfg groupMapping, log *logrus.Entry) {
for group, info := range cfg { for group, info := range cfg {
log := log.WithField("group", group) log := log.WithField("group", group)
for index, priv := range info.Privileges { for index, priv := range info.Privileges {
@ -76,7 +76,7 @@ func checkPrivMapping(cfg GroupMapping, log *logrus.Entry) {
} }
// Load and check the configuration file // Load and check the configuration file
func loadConfiguration(flags cliFlags) (configuration Configuration) { func loadConfiguration(flags cliFlags) (cfg configuration) {
log := log.WithField("config", flags.cfgFile) log := log.WithField("config", flags.cfgFile)
log.Trace("Loading configuration") log.Trace("Loading configuration")
cfgData, err := ioutil.ReadFile(flags.cfgFile) cfgData, err := ioutil.ReadFile(flags.cfgFile)
@ -84,17 +84,17 @@ func loadConfiguration(flags cliFlags) (configuration Configuration) {
log.WithField("error", err).Fatal("Could not load configuration") log.WithField("error", err).Fatal("Could not load configuration")
} }
configuration = Configuration{ cfg = configuration{
Ldap: LdapConfig{ LDAP: ldapConfig{
Port: 389, Port: 389,
Tls: "no", TLS: "no",
}, },
} }
err = yaml.Unmarshal(cfgData, &configuration) err = yaml.Unmarshal(cfgData, &cfg)
if err != nil { if err != nil {
log.WithField("error", err).Fatal("Could not parse configuration") log.WithField("error", err).Fatal("Could not parse configuration")
} }
checkPrivMapping(configuration.Mapping, log) checkPrivMapping(cfg.Mapping, log)
return return
} }

View file

@ -13,15 +13,15 @@ import (
type ( type (
// A Graylog user and associated roles // A Graylog user and associated roles
GraylogUser struct { graylogUser struct {
Username string Username string
Roles []string Roles []string
} }
// The response obtained when querying the Graylog server for a list of users. // The response obtained when querying the Graylog server for a list of users.
GlUsers struct { graylogUsers struct {
Users []struct { Users []struct {
GraylogUser graylogUser
External bool External bool
} }
} }
@ -53,16 +53,16 @@ var (
) )
// Execute a Graylog API request, returning the status code and the body // Execute a Graylog API request, returning the status code and the body
func executeApiCall(cfg GraylogConfig, method string, path string, data io.Reader) (status int, body []byte) { func executeAPICall(cfg graylogConfig, method string, path string, data io.Reader) (status int, body []byte) {
log := log.WithFields(logrus.Fields{ log := log.WithFields(logrus.Fields{
"base": cfg.ApiBase, "base": cfg.APIBase,
"username": cfg.Username, "username": cfg.Username,
"method": method, "method": method,
"path": path, "path": path,
}) })
log.Trace("Executing Graylog API call") log.Trace("Executing Graylog API call")
client := &http.Client{} client := &http.Client{}
request, err := http.NewRequest(method, fmt.Sprintf("%s/%s", cfg.ApiBase, path), data) request, err := http.NewRequest(method, fmt.Sprintf("%s/%s", cfg.APIBase, path), data)
if err != nil { if err != nil {
log.WithField("error", err).Fatal("Could not create HTTP request") log.WithField("error", err).Fatal("Could not create HTTP request")
} }
@ -86,22 +86,22 @@ func executeApiCall(cfg GraylogConfig, method string, path string, data io.Reade
} }
// Get the list of Graylog users that have been imported from LDAP // Get the list of Graylog users that have been imported from LDAP
func getGraylogUsers(configuration GraylogConfig) (users []GraylogUser) { func getGraylogUsers(configuration graylogConfig) (users []graylogUser) {
log.Trace("Getting users from the Graylog API") log.Trace("Getting users from the Graylog API")
status, body := executeApiCall(configuration, "GET", "users", nil) status, body := executeAPICall(configuration, "GET", "users", nil)
if status != 200 { if status != 200 {
log.WithField("status", status).Fatal("Could not read users") log.WithField("status", status).Fatal("Could not read users")
} }
data := GlUsers{} data := graylogUsers{}
if err := json.Unmarshal(body, &data); err != nil { if err := json.Unmarshal(body, &data); err != nil {
log.WithField("error", err).Fatal("Could not parse Graylog's user list") log.WithField("error", err).Fatal("Could not parse Graylog's user list")
} }
users = make([]GraylogUser, 0) users = make([]graylogUser, 0)
for _, item := range data.Users { for _, item := range data.Users {
if item.External { if item.External {
users = append(users, item.GraylogUser) users = append(users, item.graylogUser)
} }
} }
log.WithField("users", len(users)).Info("Obtained users from the Graylog API") log.WithField("users", len(users)).Info("Obtained users from the Graylog API")
@ -109,7 +109,7 @@ func getGraylogUsers(configuration GraylogConfig) (users []GraylogUser) {
} }
// List groups an user is a member of. // List groups an user is a member of.
func getUserGroups(user string, membership GroupMembers) (groups []string) { func getUserGroups(user string, membership ldapGroupMembers) (groups []string) {
groups = make([]string, 0) groups = make([]string, 0)
for group, members := range membership { for group, members := range membership {
for _, member := range members { for _, member := range members {
@ -123,7 +123,7 @@ func getUserGroups(user string, membership GroupMembers) (groups []string) {
} }
// Compute roles that should apply to an user // Compute roles that should apply to an user
func computeRoles(mapping GroupMapping, membership []string) (roles []string) { func computeRoles(mapping groupMapping, membership []string) (roles []string) {
rset := make(map[string]bool) rset := make(map[string]bool)
for _, group := range membership { for _, group := range membership {
for _, role := range mapping[group].Roles { for _, role := range mapping[group].Roles {
@ -141,7 +141,7 @@ func computeRoles(mapping GroupMapping, membership []string) (roles []string) {
} }
// Compute privileges on Graylog objects that should be granted to an user // Compute privileges on Graylog objects that should be granted to an user
func computePrivileges(mapping GroupMapping, membership []string) (privileges []string) { func computePrivileges(mapping groupMapping, membership []string) (privileges []string) {
type privInfo struct { type privInfo struct {
otp, oid string otp, oid string
priv int priv int
@ -149,7 +149,7 @@ func computePrivileges(mapping GroupMapping, membership []string) (privileges []
rset := make(map[string]privInfo) rset := make(map[string]privInfo)
for _, group := range membership { for _, group := range membership {
for _, priv := range mapping[group].Privileges { for _, priv := range mapping[group].Privileges {
key := fmt.Sprintf("%s:%s", priv.Type, priv.Id) key := fmt.Sprintf("%s:%s", priv.Type, priv.ID)
record, ok := rset[key] record, ok := rset[key]
level := privLevels[priv.Level] level := privLevels[priv.Level]
if ok && level <= record.priv { if ok && level <= record.priv {
@ -157,7 +157,7 @@ func computePrivileges(mapping GroupMapping, membership []string) (privileges []
} }
if !ok { if !ok {
record.otp = priv.Type record.otp = priv.Type
record.oid = priv.Id record.oid = priv.ID
} }
record.priv = level record.priv = level
rset[key] = record rset[key] = record
@ -176,10 +176,10 @@ func computePrivileges(mapping GroupMapping, membership []string) (privileges []
} }
// Delete a Graylog user account // Delete a Graylog user account
func deleteAccount(cfg GraylogConfig, user string) { func deleteAccount(cfg graylogConfig, user string) {
log := log.WithField("user", user) log := log.WithField("user", user)
log.Warning("Deleting Graylog account") log.Warning("Deleting Graylog account")
code, body := executeApiCall(cfg, "DELETE", fmt.Sprintf("/users/%s", user), nil) code, body := executeAPICall(cfg, "DELETE", fmt.Sprintf("/users/%s", user), nil)
if code != 204 { if code != 204 {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"status": code, "status": code,
@ -207,7 +207,7 @@ func getDifference(a []string, b []string) (diff []string) {
} }
// Set an account's roles and grant it access to Graylog objects // Set an account's roles and grant it access to Graylog objects
func setUserPrivileges(cfg GraylogConfig, user GraylogUser, roles []string, privileges []string) { func setUserPrivileges(cfg graylogConfig, user graylogUser, roles []string, privileges []string) {
log := log.WithField("user", user.Username) log := log.WithField("user", user.Username)
type perms struct { type perms struct {
@ -219,7 +219,7 @@ func setUserPrivileges(cfg GraylogConfig, user GraylogUser, roles []string, priv
log.WithField("error", err).Fatal("Unable to generate permissions JSON") log.WithField("error", err).Fatal("Unable to generate permissions JSON")
} }
log.WithField("privileges", privileges).Info("Setting permissions") log.WithField("privileges", privileges).Info("Setting permissions")
code, body := executeApiCall(cfg, "PUT", code, body := executeAPICall(cfg, "PUT",
fmt.Sprintf("users/%s/permissions", user.Username), fmt.Sprintf("users/%s/permissions", user.Username),
bytes.NewBuffer(data)) bytes.NewBuffer(data))
if code != 204 { if code != 204 {
@ -233,7 +233,7 @@ func setUserPrivileges(cfg GraylogConfig, user GraylogUser, roles []string, priv
for _, role := range getDifference(roles, user.Roles) { for _, role := range getDifference(roles, user.Roles) {
ep := fmt.Sprintf("roles/%s/members/%s", role, user.Username) ep := fmt.Sprintf("roles/%s/members/%s", role, user.Username)
log.WithField("role", role).Info("Adding role") log.WithField("role", role).Info("Adding role")
code, body := executeApiCall(cfg, "PUT", ep, placeholder) code, body := executeAPICall(cfg, "PUT", ep, placeholder)
if code != 204 { if code != 204 {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"status": code, "status": code,
@ -245,7 +245,7 @@ func setUserPrivileges(cfg GraylogConfig, user GraylogUser, roles []string, priv
for _, role := range getDifference(user.Roles, roles) { for _, role := range getDifference(user.Roles, roles) {
ep := fmt.Sprintf("roles/%s/members/%s", role, user.Username) ep := fmt.Sprintf("roles/%s/members/%s", role, user.Username)
log.WithField("role", role).Info("Removing role") log.WithField("role", role).Info("Removing role")
code, body := executeApiCall(cfg, "DELETE", ep, nil) code, body := executeAPICall(cfg, "DELETE", ep, nil)
if code != 204 { if code != 204 {
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"status": code, "status": code,
@ -257,7 +257,7 @@ func setUserPrivileges(cfg GraylogConfig, user GraylogUser, roles []string, priv
} }
// Apply privilege mappings to the external Graylog users // Apply privilege mappings to the external Graylog users
func applyMapping(cfg Configuration, users []GraylogUser, groups GroupMembers) { func applyMapping(cfg configuration, users []graylogUser, groups ldapGroupMembers) {
for _, user := range users { for _, user := range users {
log := log.WithField("user", user.Username) log := log.WithField("user", user.Username)
membership := getUserGroups(user.Username, groups) membership := getUserGroups(user.Username, groups)

24
ldap.go
View file

@ -17,28 +17,28 @@ type (
ldapConn struct { ldapConn struct {
conn *ldap.Conn conn *ldap.Conn
log *logrus.Entry log *logrus.Entry
cfg LdapConfig cfg ldapConfig
usernames map[string]string usernames map[string]string
counter uint counter uint
} }
// LDAP group members // LDAP group members
GroupMembers map[string][]string ldapGroupMembers map[string][]string
) )
// Establish a connection to the LDAP server // Establish a connection to the LDAP server
func getLdapConnection(cfg LdapConfig) *ldapConn { func getLdapConnection(cfg ldapConfig) *ldapConn {
dest := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) dest := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
log := log.WithFields(logrus.Fields{ log := log.WithFields(logrus.Fields{
"ldap_server": dest, "ldap_server": dest,
"ldap_tls": cfg.Tls, "ldap_tls": cfg.TLS,
}) })
log.Trace("Establishing LDAP connection") log.Trace("Establishing LDAP connection")
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: cfg.TlsNoVerify, InsecureSkipVerify: cfg.TLSNoVerify,
} }
if cfg.Tls != "no" && cfg.CaChain != "" { if cfg.TLS != "no" && cfg.CaChain != "" {
log := log.WithField("cachain", cfg.CaChain) log := log.WithField("cachain", cfg.CaChain)
data, err := ioutil.ReadFile(cfg.CaChain) data, err := ioutil.ReadFile(cfg.CaChain)
if err != nil { if err != nil {
@ -53,7 +53,7 @@ func getLdapConnection(cfg LdapConfig) *ldapConn {
var err error var err error
var lc *ldap.Conn var lc *ldap.Conn
if cfg.Tls == "yes" { if cfg.TLS == "yes" {
lc, err = ldap.DialTLS("tcp", dest, tlsConfig) lc, err = ldap.DialTLS("tcp", dest, tlsConfig)
} else { } else {
lc, err = ldap.Dial("tcp", dest) lc, err = ldap.Dial("tcp", dest)
@ -62,7 +62,7 @@ func getLdapConnection(cfg LdapConfig) *ldapConn {
log.WithField("error", err).Fatal("Failed to connect to the LDAP server") log.WithField("error", err).Fatal("Failed to connect to the LDAP server")
} }
if cfg.Tls == "starttls" { if cfg.TLS == "starttls" {
err = lc.StartTLS(tlsConfig) err = lc.StartTLS(tlsConfig)
if err != nil { if err != nil {
lc.Close() lc.Close()
@ -201,11 +201,11 @@ func (conn *ldapConn) getGroupMembers(group string) (members []string) {
} }
// Read the list of group members from the LDAP server for all groups in the mapping section. // Read the list of group members from the LDAP server for all groups in the mapping section.
func readLdapGroups(configuration Configuration) GroupMembers { func readLdapGroups(cfg configuration) ldapGroupMembers {
conn := getLdapConnection(configuration.Ldap) conn := getLdapConnection(cfg.LDAP)
defer conn.close() defer conn.close()
groups := make(GroupMembers) groups := make(ldapGroupMembers)
for group := range configuration.Mapping { for group := range cfg.Mapping {
groups[group] = conn.getGroupMembers(group) groups[group] = conn.getGroupMembers(group)
} }
return groups return groups