f43bc981e9
This is mainly to avoid having the API return "0001-01-01T00:00:00Z" as a value for the ExpirationTime field when it is not set. Unfortunately time.Time doesn't respect the json marshalling "omitempty" directive.
231 lines
6.6 KiB
Go
231 lines
6.6 KiB
Go
package acl
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/consul/agent/structs"
|
|
"github.com/hashicorp/consul/api"
|
|
"github.com/mitchellh/cli"
|
|
)
|
|
|
|
func PrintToken(token *api.ACLToken, ui cli.Ui, showMeta bool) {
|
|
ui.Info(fmt.Sprintf("AccessorID: %s", token.AccessorID))
|
|
ui.Info(fmt.Sprintf("SecretID: %s", token.SecretID))
|
|
ui.Info(fmt.Sprintf("Description: %s", token.Description))
|
|
ui.Info(fmt.Sprintf("Local: %t", token.Local))
|
|
ui.Info(fmt.Sprintf("Create Time: %v", token.CreateTime))
|
|
if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() {
|
|
ui.Info(fmt.Sprintf("Expiration Time: %v", *token.ExpirationTime))
|
|
}
|
|
if showMeta {
|
|
ui.Info(fmt.Sprintf("Hash: %x", token.Hash))
|
|
ui.Info(fmt.Sprintf("Create Index: %d", token.CreateIndex))
|
|
ui.Info(fmt.Sprintf("Modify Index: %d", token.ModifyIndex))
|
|
}
|
|
ui.Info(fmt.Sprintf("Policies:"))
|
|
for _, policy := range token.Policies {
|
|
ui.Info(fmt.Sprintf(" %s - %s", policy.ID, policy.Name))
|
|
}
|
|
ui.Info(fmt.Sprintf("Service Identities:"))
|
|
for _, svcid := range token.ServiceIdentities {
|
|
if len(svcid.Datacenters) > 0 {
|
|
ui.Info(fmt.Sprintf(" %s (Datacenters: %s)", svcid.ServiceName, strings.Join(svcid.Datacenters, ", ")))
|
|
} else {
|
|
ui.Info(fmt.Sprintf(" %s (Datacenters: all)", svcid.ServiceName))
|
|
}
|
|
}
|
|
if token.Rules != "" {
|
|
ui.Info(fmt.Sprintf("Rules:"))
|
|
ui.Info(token.Rules)
|
|
}
|
|
}
|
|
|
|
func PrintTokenListEntry(token *api.ACLTokenListEntry, ui cli.Ui, showMeta bool) {
|
|
ui.Info(fmt.Sprintf("AccessorID: %s", token.AccessorID))
|
|
ui.Info(fmt.Sprintf("Description: %s", token.Description))
|
|
ui.Info(fmt.Sprintf("Local: %t", token.Local))
|
|
ui.Info(fmt.Sprintf("Create Time: %v", token.CreateTime))
|
|
if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() {
|
|
ui.Info(fmt.Sprintf("Expiration Time: %v", *token.ExpirationTime))
|
|
}
|
|
ui.Info(fmt.Sprintf("Legacy: %t", token.Legacy))
|
|
if showMeta {
|
|
ui.Info(fmt.Sprintf("Hash: %x", token.Hash))
|
|
ui.Info(fmt.Sprintf("Create Index: %d", token.CreateIndex))
|
|
ui.Info(fmt.Sprintf("Modify Index: %d", token.ModifyIndex))
|
|
}
|
|
ui.Info(fmt.Sprintf("Policies:"))
|
|
for _, policy := range token.Policies {
|
|
ui.Info(fmt.Sprintf(" %s - %s", policy.ID, policy.Name))
|
|
}
|
|
ui.Info(fmt.Sprintf("Service Identities:"))
|
|
for _, svcid := range token.ServiceIdentities {
|
|
if len(svcid.Datacenters) > 0 {
|
|
ui.Info(fmt.Sprintf(" %s (Datacenters: %s)", svcid.ServiceName, strings.Join(svcid.Datacenters, ", ")))
|
|
} else {
|
|
ui.Info(fmt.Sprintf(" %s (Datacenters: all)", svcid.ServiceName))
|
|
}
|
|
}
|
|
}
|
|
|
|
func PrintPolicy(policy *api.ACLPolicy, ui cli.Ui, showMeta bool) {
|
|
ui.Info(fmt.Sprintf("ID: %s", policy.ID))
|
|
ui.Info(fmt.Sprintf("Name: %s", policy.Name))
|
|
ui.Info(fmt.Sprintf("Description: %s", policy.Description))
|
|
ui.Info(fmt.Sprintf("Datacenters: %s", strings.Join(policy.Datacenters, ", ")))
|
|
if showMeta {
|
|
ui.Info(fmt.Sprintf("Hash: %x", policy.Hash))
|
|
ui.Info(fmt.Sprintf("Create Index: %d", policy.CreateIndex))
|
|
ui.Info(fmt.Sprintf("Modify Index: %d", policy.ModifyIndex))
|
|
}
|
|
ui.Info(fmt.Sprintf("Rules:"))
|
|
ui.Info(policy.Rules)
|
|
}
|
|
|
|
func PrintPolicyListEntry(policy *api.ACLPolicyListEntry, ui cli.Ui, showMeta bool) {
|
|
ui.Info(fmt.Sprintf("%s:", policy.Name))
|
|
ui.Info(fmt.Sprintf(" ID: %s", policy.ID))
|
|
ui.Info(fmt.Sprintf(" Description: %s", policy.Description))
|
|
ui.Info(fmt.Sprintf(" Datacenters: %s", strings.Join(policy.Datacenters, ", ")))
|
|
if showMeta {
|
|
ui.Info(fmt.Sprintf(" Hash: %x", policy.Hash))
|
|
ui.Info(fmt.Sprintf(" Create Index: %d", policy.CreateIndex))
|
|
ui.Info(fmt.Sprintf(" Modify Index: %d", policy.ModifyIndex))
|
|
}
|
|
}
|
|
|
|
func GetTokenIDFromPartial(client *api.Client, partialID string) (string, error) {
|
|
if partialID == "anonymous" {
|
|
return structs.ACLTokenAnonymousID, nil
|
|
}
|
|
|
|
// the full UUID string was given
|
|
if len(partialID) == 36 {
|
|
return partialID, nil
|
|
}
|
|
|
|
tokens, _, err := client.ACL().TokenList(nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
tokenID := ""
|
|
for _, token := range tokens {
|
|
if strings.HasPrefix(token.AccessorID, partialID) {
|
|
if tokenID != "" {
|
|
return "", fmt.Errorf("Partial token ID is not unique")
|
|
}
|
|
tokenID = token.AccessorID
|
|
}
|
|
}
|
|
|
|
if tokenID == "" {
|
|
return "", fmt.Errorf("No such token ID with prefix: %s", partialID)
|
|
}
|
|
|
|
return tokenID, nil
|
|
}
|
|
|
|
func GetPolicyIDFromPartial(client *api.Client, partialID string) (string, error) {
|
|
if partialID == "global-management" {
|
|
return structs.ACLPolicyGlobalManagementID, nil
|
|
}
|
|
// The full UUID string was given
|
|
if len(partialID) == 36 {
|
|
return partialID, nil
|
|
}
|
|
|
|
policies, _, err := client.ACL().PolicyList(nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
policyID := ""
|
|
for _, policy := range policies {
|
|
if strings.HasPrefix(policy.ID, partialID) {
|
|
if policyID != "" {
|
|
return "", fmt.Errorf("Partial policy ID is not unique")
|
|
}
|
|
policyID = policy.ID
|
|
}
|
|
}
|
|
|
|
if policyID == "" {
|
|
return "", fmt.Errorf("No such policy ID with prefix: %s", partialID)
|
|
}
|
|
|
|
return policyID, nil
|
|
}
|
|
|
|
func GetPolicyIDByName(client *api.Client, name string) (string, error) {
|
|
if name == "" {
|
|
return "", fmt.Errorf("No name specified")
|
|
}
|
|
|
|
policies, _, err := client.ACL().PolicyList(nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for _, policy := range policies {
|
|
if policy.Name == name {
|
|
return policy.ID, nil
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("No such policy with name %s", name)
|
|
}
|
|
|
|
func GetRulesFromLegacyToken(client *api.Client, tokenID string, isSecret bool) (string, error) {
|
|
tokenID, err := GetTokenIDFromPartial(client, tokenID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var token *api.ACLToken
|
|
if isSecret {
|
|
qopts := api.QueryOptions{
|
|
Token: tokenID,
|
|
}
|
|
token, _, err = client.ACL().TokenReadSelf(&qopts)
|
|
} else {
|
|
token, _, err = client.ACL().TokenRead(tokenID, nil)
|
|
}
|
|
|
|
if err != nil {
|
|
return "", fmt.Errorf("Error reading token: %v", err)
|
|
}
|
|
|
|
if token == nil {
|
|
return "", fmt.Errorf("Token not found for ID")
|
|
}
|
|
|
|
if token.Rules == "" {
|
|
return "", fmt.Errorf("Token is not a legacy token with rules")
|
|
}
|
|
|
|
return token.Rules, nil
|
|
}
|
|
|
|
func ExtractServiceIdentities(serviceIdents []string) ([]*api.ACLServiceIdentity, error) {
|
|
var out []*api.ACLServiceIdentity
|
|
for _, svcidRaw := range serviceIdents {
|
|
parts := strings.Split(svcidRaw, ":")
|
|
switch len(parts) {
|
|
case 2:
|
|
out = append(out, &api.ACLServiceIdentity{
|
|
ServiceName: parts[0],
|
|
Datacenters: strings.Split(parts[1], ","),
|
|
})
|
|
case 1:
|
|
out = append(out, &api.ACLServiceIdentity{
|
|
ServiceName: parts[0],
|
|
})
|
|
default:
|
|
return nil, fmt.Errorf("Malformed -service-identity argument: %q", svcidRaw)
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|