...
 
Commits (2)
image: golang:1.12
include:
- template: SAST.gitlab-ci.yml
- template: License-Management.gitlab-ci.yml
stages:
......
......@@ -38,22 +38,42 @@ aim-client init
source <(aim-client --completion-script-bash)
```
## create an authorization for an identity
## create a new identity
```
aim-client create authz myid.example.org en
aim-client get authz myid.example.org
usage: aim-client create id <id> [<flags>]
aim-client create id myid_office.example.org -m myofficemail@example.org -l de
```
## create and add a new identity to a subject
```
usage: aim-client sub add <id> <sub> [<flags>]
aim-client sub add myid_private.example.org fkwbfkh./lks -m myprivatemail@example.org -l de
```
## signal that the acme-challenge is solved
## get details/ authorization/ identifiers/ transfer of a subject
```
aim-client activate id myid.example.org
usage: aim-client sub get <object> <sub>
aim-client sub get details fkwbfkh./lks
aim-client sub get authz fkwbfkh./lks
aim-client sub get identifiers fkwbfkh./lks
aim-client sub get transfer fkwbfkh./lks
```
## get the password setup url for the activated id
## perform a subject transfer
```
aim-client get id myid.example.org
usage: aim-client sub transfer <sub>
aim-client sub transfer fkwbfkh./lks
```
# Hooks for mail and dns
......
This diff is collapsed.
......@@ -19,13 +19,13 @@ var appconfig = &config.AppConfig{
FullName: "client-full-name",
Email: "mail@client",
},
AimURL: "https://id.staging.denic.de/aim/v1",
AimURL: "https://id.staging.denic.de/aim/v2",
}
func TestNewClient(t *testing.T) {
t.Run("init a new client", func(t *testing.T) {
c, err := Init(appconfig)
c, err := Init(appconfig, "", true)
if !assert.NoError(t, err, "new client must be initialized.") {
return
}
......@@ -35,45 +35,45 @@ func TestNewClient(t *testing.T) {
})
t.Run("create a new client", func(t *testing.T) {
_, err := NewFromConfig(appconfig)
_, err := NewFromConfig(appconfig, "", true)
if !assert.NoError(t, err, "New client must be created") {
return
}
})
t.Run("exists at authority", func(t *testing.T) {
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", true)
if !assert.NoError(t, err, "New client must be created") {
return
}
exists, _, err := c.existsAtAuthority()
exists, err := c.GetOwnAgent()
if !assert.NoError(t, err, "check client for existance at authority must not fail.") {
return
}
if !assert.Equal(t, true, exists, "client must exist at authority") {
if !assert.Equal(t, nil, exists, "client must exist at authority") {
return
}
})
t.Run("create at authority", func(t *testing.T) {
appconfig.Client.Name = fmt.Sprintf("denic-test-%s", uniuri.NewLen(8))
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", true)
if !assert.NoError(t, err, "New client must be created") {
return
}
err = c.CreateAtAuthority()
_, err = c.CreateAgent()
if !assert.NoError(t, err, "Client must be created at the authority.") {
return
}
exists, _, err := c.existsAtAuthority()
exists, err := c.GetOwnAgent()
if !assert.NoError(t, err, "check client for existance at authority must not fail.") {
return
}
if !assert.Equal(t, true, exists, "client must exist at authority") {
if !assert.Equal(t, nil, exists, "client must exist at authority") {
return
}
})
......@@ -82,17 +82,17 @@ func TestNewClient(t *testing.T) {
func TestClientExists(t *testing.T) {
t.Run("existing at authority", func(t *testing.T) {
//appconfig.Client.Name = fmt.Sprintf("denic-test-%s", uniuri.NewLen(8))
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", true)
if !assert.NoError(t, err, "New client must be created") {
return
}
exists, _, err := c.existsAtAuthority()
exists, err := c.GetOwnAgent()
if !assert.NoError(t, err, "check client for existance at authority must not fail.") {
return
}
if !assert.Equal(t, true, exists, "client must exist at authority") {
if !assert.Equal(t, nil, exists, "client must exist at authority") {
return
}
})
......@@ -100,77 +100,77 @@ func TestClientExists(t *testing.T) {
func TestClientPostNewIdAuthz(t *testing.T) {
t.Run("create new authz", func(t *testing.T) {
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", false)
if !assert.NoError(t, err, "New client must be created") {
return
}
id := fmt.Sprintf("%s.foobar.bla", uniuri.NewLen(8))
authz, err := c.postNewIdentityAuthz(id, "de")
authz, err := c.CreateAndSaveIdentityAuthz("",id, "de", "dummy@gmail.com", false)
if !assert.NoError(t, err, "post new id must not fail.") {
return
}
challenge, err := c.CreateAcmeChallenge(authz.Challenge.Token)
challenge, err := c.CreateAcmeChallenge(authz.Token)
fmt.Println(challenge)
})
id := fmt.Sprintf("%s.foobar.bla", uniuri.NewLen(8))
t.Run("create new authz and write yaml", func(t *testing.T) {
appconfig.AuthzDir = "."
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", false)
if !assert.NoError(t, err, "New client must be created") {
return
}
authz, err := c.postNewIdentityAuthz(id, "de")
authz, err := c.CreateAndSaveIdentityAuthz("",id, "de", "dummy@gmail.com", false)
if !assert.NoError(t, err, "post new id must not fail.") {
return
}
err = utils.AuthzToYamlFile(authz, ".")
err = utils.AuthzToYamlFile(authz, ".", false)
if !assert.NoError(t, err, "Auth file must be created.") {
return
}
challenge, err := c.CreateAcmeChallenge(authz.Challenge.Token)
challenge, err := c.CreateAcmeChallenge(authz.Token)
fmt.Println(challenge)
})
t.Run("create and save new authz", func(t *testing.T) {
appconfig.AuthzDir = "."
id := fmt.Sprintf("%s.foobar.bla", uniuri.NewLen(8))
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", false)
if !assert.NoError(t, err, "New client must be created") {
return
}
authz, err := c.CreateAndSaveIdentityAuthz(id, "de")
authz, err := c.CreateAndSaveIdentityAuthz("",id, "de", "dummy@gmail.com", false)
if !assert.NoError(t, err, "post new id must not fail.") {
return
}
challenge, err := c.CreateAcmeChallenge(authz.Challenge.Token)
challenge, err := c.CreateAcmeChallenge(authz.Token)
fmt.Println(challenge)
})
t.Run("load authz from file and get authz", func(t *testing.T) {
appconfig.AuthzDir = "."
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", false)
if !assert.NoError(t, err, "New client must be created") {
return
}
authz, err := utils.AuthzFromYamlFile(".", id)
authz, err := utils.AuthzFromYamlFile(".", id, false)
if !assert.NoError(t, err, "authz must be loaded from file") {
return
}
authzAtAuthority, err := c.getIdentityAuthz(authz.Identifier)
authzAtAuthority, err := c.GetIdentityAuthz("", authz.Identifier, false)
if !assert.NoError(t, err, "must get authz from authority") {
return
}
if !assert.Equal(t, authz.Challenge.Token, authzAtAuthority.Challenge.Token, "Authz must be equal") {
if !assert.Equal(t, authz.Token, authzAtAuthority.Token, "Authz must be equal") {
return
}
})
......@@ -179,23 +179,23 @@ func TestClientPostNewIdAuthz(t *testing.T) {
func TestClientPostIdAuthzReady(t *testing.T) {
appconfig.AuthzDir = "."
id := fmt.Sprintf("%s.foobar.bla", uniuri.NewLen(8))
c, err := NewFromConfig(appconfig)
c, err := NewFromConfig(appconfig, "", true)
if !assert.NoError(t, err, "New client must be created") {
return
}
_, err = c.CreateAndSaveIdentityAuthz(id, "de")
_, err = c.CreateAndSaveIdentityAuthz("", id, "de","dummy@gmail.com",false)
if !assert.NoError(t, err, "post new id must not fail.") {
return
}
t.Run("post id ready", func(t *testing.T) {
authz, err := c.postAcmeSetUp(id)
authz, err := c.PostAcmeSetupDone("",id, false)
if !assert.NoError(t, err, "must get authz from authority") {
return
}
if assert.Equal(t, nil, authz.Challenge.Validated, "Fucked up.") {
if assert.Equal(t, nil, authz.Validated, "Fucked up.") {
return
}
})
......
......@@ -11,7 +11,8 @@ var (
FailedCreateIdAuthzError = errors.New("FailedCreateIdAuthz").Msg("failed to create authz for identity: %s")
HttpClientError = errors.New("HttpClientError").Msg("http request failed: %s")
FailedIdAuthzSetUpError = errors.New("FailedIdAuthzSetUpError").Msg("failed to post id set up: %s")
GetIdentityError = errors.New("GetIdentityError").Msg("failed to get identity: %s")
GetSubjectError = errors.New("GetSubjectError").Msg("failed to get subject identity: %s")
FailedUpdateAgentError = errors.New("FailedUpdateAgentError").Msg("failed to update the agent: %s")
DryRunError = errors.New("DryRunError").Msg("DryRun does not have a response.")
UndefinedScopeError = errors.New("UndefinedScopeError").Msg("undefined scope/use case: %s")
)
package client
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
......@@ -10,10 +8,9 @@ import (
"github.com/kr/pretty"
"gitlab.com/denic-id/aim-client/crypto"
"gitlab.com/denic-id/aim-client/models"
"gitlab.com/denic-id/aim-client/utils"
)
// getBodyString retrieves the body of the given http response as string
func getBodyString(resp *http.Response) string {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
......@@ -22,6 +19,7 @@ func getBodyString(resp *http.Response) string {
return string(body)
}
// getBodyBytes retrieves the body of the given http response as a slice of bytes
func getBodyBytes(resp *http.Response) []byte {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
......@@ -31,13 +29,15 @@ func getBodyBytes(resp *http.Response) []byte {
return body
}
func (c *Client) DoRequest(r *http.Request) (*http.Response, error) {
// doRequest performs the fiven http request and returns its response
func (c *Client) doRequest(r *http.Request) (*http.Response, error) {
if c.IsDryRun() {
return &http.Response{}, DryRunError.Make()
}
return c.httpClient.Do(r)
}
// newRequest creates a new http request with the given parameters
func (c *Client) newRequest(method, url, payload string, withKeyID, embedKey bool) (*http.Request, error) {
req, err := http.NewRequest(method, url, strings.NewReader(payload))
if err != nil {
......@@ -51,8 +51,10 @@ func (c *Client) newRequest(method, url, payload string, withKeyID, embedKey boo
s.SetOption("b64", false)
s.SetOption("url", url)
s.SetOption("method", method)
s.SetOption("kid", c.key.KeyID)
s.EmbedKey(false)
if withKeyID {
s.SetOption("kid", c.key.KeyID)
}
s.EmbedKey(embedKey)
jws, err := s.SignPayload(payload)
if err != nil {
......@@ -71,295 +73,21 @@ func (c *Client) newRequest(method, url, payload string, withKeyID, embedKey boo
return req, nil
}
func (c *Client) RawRequest(url, method, payload, keyfile string) (http.Header, string, error) {
if len(keyfile) > 0 {
key, err := crypto.ReadKeyFromFile(keyfile)
if err != nil {
return nil, "", err
}
c.key = key
}
r, err := c.newRequest(method, url, payload, true, false)
if err != nil {
return nil, "", err
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, "", err
}
return resp.Header, getBodyString(resp), nil
}
func (c *Client) existsAtAuthority() (bool, *http.Response, error) {
url := fmt.Sprintf("%s/%s/%s", c.config.AimURL, "agents", c.key.KeyID)
r, err := c.newRequest(http.MethodGet, url, "", true, false)
if err != nil {
return false, nil, err
}
resp, err := c.DoRequest(r)
if err != nil {
return false, nil, err
}
if resp.StatusCode != 200 {
return false, resp, nil
}
return true, resp, nil
}
func (c *Client) postNewAgent() (*models.Agent, error) {
url := fmt.Sprintf("%s/%s", c.config.AimURL, "agents")
var agent models.Agent
agent.Name = c.config.Client.Name
agent.FullName = c.config.Client.FullName
agent.Email = c.config.Client.Email
agent.IssuerURL = c.config.Client.IssuerURL
agent.Keys = append(agent.Keys, c.key.Public())
payloadbytes, err := json.Marshal(agent)
if err != nil {
return nil, err
}
//prettypayload, _ := json.MarshalIndent(agent, "", " ")(agent)
// createAndExecuteRequest generates http request according the given data and returns the corresponding response handle plus body
func (c *Client) createAndExecuteRequest(httpMethod string, url string, payload []byte, withkeyID bool, embedKey bool) (*http.Response, []byte, error) {
//pretty.Println("sending payload:", string(payloadbytes))
r, err := c.newRequest(http.MethodPost, url, string(payloadbytes), false, true)
// create request
req, err := c.newRequest(httpMethod, url, string(payload), withkeyID, embedKey)
if err != nil {
return nil, err
return nil, nil, err
}
//pretty.Println("sending jws:", r.Header.Get("jws-detached-signature"))
resp, err := c.DoRequest(r)
// perform request
resp, err := c.doRequest(req)
if err != nil {
return nil, err
}
body := getBodyBytes(resp)
if resp.StatusCode != 201 {
return nil, FailedCreateAgentError.Args(string(body)).Make()
}
if err := json.Unmarshal(body, &agent); err != nil {
return nil, FailedCreateAgentError.Args(err.Error()).Make()
}
pretty.Println("received:", string(body))
return &agent, nil
}
func (c *Client) putAgent(agent *models.Agent) error {
payloadbytes, err := json.Marshal(agent)
if err != nil {
return GenericClientError.Args(err.Error()).Make()
}
url := fmt.Sprintf("%s/%s", c.config.AimURL, "agents/"+c.config.Client.ID)
r, err := c.newRequest(http.MethodPut, url, string(payloadbytes), true, false)
if err != nil {
return HttpClientError.Args(err.Error()).Make()
}
resp, err := c.DoRequest(r)
if err != nil {
return HttpClientError.Args(err.Error()).Make()
}
body := getBodyBytes(resp)
if resp.StatusCode != 200 {
return FailedUpdateAgentError.Args(string(body)).Make()
}
err = json.Unmarshal(body, agent)
if err != nil {
return FailedUpdateAgentError.Args(string(body)).Make()
}
return nil
}
func (c *Client) postNewIdentityAuthz(identifier, locale string) (*models.IdentityAuthz, error) {
var idauthz models.IdentityAuthzRequest
idauthz.Identifier = identifier
idauthz.Locale = locale
url := fmt.Sprintf("%s/%s", c.config.AimURL, "authz")
payloadbytes, err := json.Marshal(idauthz)
if err != nil {
return nil, GenericClientError.Args(err.Error()).Make()
}
r, err := c.newRequest(http.MethodPost, url, string(payloadbytes), true, true)
if err != nil {
return nil, HttpClientError.Args(err.Error()).Make()
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, HttpClientError.Args(err.Error()).Make()
}
body := getBodyBytes(resp)
if resp.StatusCode != 201 {
return nil, FailedCreateIdAuthzError.Args(string(body)).Make()
}
var idauthzresponse models.IdentityAuthz
if err := json.Unmarshal(body, &idauthzresponse); err != nil {
return nil, FailedCreateIdAuthzError.Args(err.Error()).Make()
}
return &idauthzresponse, nil
}
func (c *Client) getIdentityAuthz(id string) (*models.IdentityAuthz, error) {
authz, err := utils.AuthzFromYamlFile(c.config.AuthzDir, id)
if err != nil {
return nil, err
return nil, nil, err
}
url := fmt.Sprintf("%s/%s/%d", c.config.AimURL, "authz/id", authz.ID)
r, err := c.newRequest(http.MethodGet, url, "", true, false)
if err != nil {
return nil, HttpClientError.Args(err.Error()).Make()
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, HttpClientError.Args(err.Error()).Make()
}
body := getBodyBytes(resp)
if resp.StatusCode != 200 {
return nil, FailedCreateIdAuthzError.Args(string(body)).Make()
}
var idauthzresponse models.IdentityAuthz
if err := json.Unmarshal(body, &idauthzresponse); err != nil {
return nil, FailedCreateIdAuthzError.Args(err.Error()).Make()
}
return &idauthzresponse, nil
}
func (c *Client) postAcmeSetUp(id string) (*models.IdentityAuthz, error) {
authz, err := utils.AuthzFromYamlFile(c.config.AuthzDir, id)
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s/%s/%d", c.config.AimURL, "authz/id", authz.ID)
r, err := c.newRequest(http.MethodPost, url, "", true, false)
if err != nil {
return nil, err
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, err
}
body := getBodyBytes(resp)
if resp.StatusCode != 200 {
return nil, FailedIdAuthzSetUpError.Args(string(body)).Make()
}
var idauthzresponse models.IdentityAuthz
if err := json.Unmarshal(body, &idauthzresponse); err != nil {
return nil, FailedIdAuthzSetUpError.Args(err.Error()).Make()
}
return &idauthzresponse, nil
}
func (c *Client) getIdentity(id string) (*models.Identity, error) {
url := fmt.Sprintf("%s/%s/%s", c.config.AimURL, "identities", id)
r, err := c.newRequest(http.MethodGet, url, "", true, false)
if err != nil {
return nil, err
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, err
}
body := getBodyBytes(resp)
if resp.StatusCode != 200 {
return nil, GetIdentityError.Args(string(body)).Make()
}
var identity models.Identity
if err := json.Unmarshal(body, &identity); err != nil {
return nil, GetIdentityError.Args(err.Error()).Make()
}
return &identity, nil
}
func (c *Client) resetIdentityCredentials(id string) (*models.IdentitiesCredentialsResetResponse, error) {
identity := new(models.Identity)
err := utils.FromYamlFile(identity, c.config.AuthzDir+"/"+id+".yaml")
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s/%s/%s", c.config.AimURL, "identities", "credentialsReset")
payload := fmt.Sprintf("{\"sub\":\"%s\"}", identity.Subject)
r, err := c.newRequest(http.MethodPost, url, payload, true, false)
if err != nil {
return nil, err
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, err
}
body := getBodyBytes(resp)
if resp.StatusCode != 200 {
return nil, GetIdentityError.Args(string(body)).Make()
}
var respObj models.IdentitiesCredentialsResetResponse
if err := json.Unmarshal(body, &respObj); err != nil {
return nil, GetIdentityError.Args(err.Error()).Make()
}
return &respObj, nil
}
func (c *Client) getOwnAgent() (*models.Agent, error) {
url := fmt.Sprintf("%s/%s/%s", c.config.AimURL, "agents", c.config.Client.ID)
r, err := c.newRequest(http.MethodGet, url, "", true, false)
if err != nil {
return nil, err
}
resp, err := c.DoRequest(r)
if err != nil {
return nil, err
}
body := getBodyBytes(resp)
pretty.Println(string(body))
if resp.StatusCode != 200 {
return nil, GetAgentError.Args(fmt.Sprintf("%s -> %s", url, string(body))).Make()
}
var respObj models.Agent
if err := json.Unmarshal(body, &respObj); err != nil {
return nil, GetAgentError.Args(err.Error()).Make()
}
return &respObj, nil
// return response
return resp, getBodyBytes(resp), nil
}
{"use":"sig","kty":"EC","kid":"3ed98646-1ec1-4774-ab92-7cda483f5881","crv":"P-521","alg":"ES512","x":"ARCRtza326GLmiBtpdSAI8C--IejbHync04tUGxyscWfjeOKkIZQ2d9JpLBJr6dJ7A_DJtGCM8AlIs3gzgsTZNNO","y":"ATm-xkMq1PbArhRIii3u1BYag42mcWTgNUve6OX-4HG5oXxZoFCzU6lfn-NQvJAY_xX0WuREd8XX-HCJN9LRxkdg","d":"AAB1CzAUVW7T1eY4zbLcukZpkfyg8OjaVbFuvv13eQHj2g-ZXyJcLnoVy4hkEnKsXbbVsdaji6tuKZxgXLcci3OB"}
\ No newline at end of file
This diff is collapsed.
......@@ -12,7 +12,7 @@ type AppConfig struct {
}
type ClientConfig struct {
ID string `json:"id" yaml:"id"`
ID string `json:"id" yaml:"id"` // alias AgentID
KeyFile string `json:"keyFile" yaml:"keyFile"`
Name string `json:"name" yaml:"name"`
FullName string `json:"fullName" yaml:"fullName"`
......
......@@ -49,6 +49,7 @@ golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/square/go-jose.v2 v2.4.0 h1:0kXPskUMGAXXWJlP05ktEMOV0vmzFQUWw6d+aZJQU8A=
gopkg.in/square/go-jose.v2 v2.4.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
......
package models
import (
"fmt"
"io/ioutil"
"path/filepath"
"time"
yaml "gopkg.in/yaml.v2"
)
// Agent represents the database and application model for an identity agent
type Agent struct {
ID string `json:"agent_id,omitempty" yaml:"id"`
Keys []interface{} `json:"keys,omitempty" yaml:"keys"`
......@@ -19,30 +15,34 @@ type Agent struct {
IssuerURL string `json:"issuer_url" yaml:"issuer_url"`
}
// IdentityAuthzRequest represents the database and application model for an identity authorization request
type IdentityAuthzRequest struct {
Identifier string `json:"identifier"`
Locale string `json:"locale"`
Identifier string `json:"identifier"`
Locale string `json:"locale"`
}
// IdentityAuthz represents the database and application model for an identity authorization.
type IdentityAuthz struct {
ID int64 `json:"identifier_authz_id" yaml:"id"`
Identifier string `json:"identifier" yaml:"identifier"`
Email string `json:"-" yaml:"email,omitempty"`
Expires time.Time `json:"expiration_ts" yaml:"expiration_ts"`
Validated time.Time `json:"validation_ts" yaml:"validation_ts"`
InitURL string `json:"init_url" yaml:"init_url"`
InitURLExpires time.Time `json:"init_url_expiration_ts" yaml:"init_url_expiration_ts"`
Token string `json:"token" yaml:"token"`
Subject string `json:"sub" yaml:"sub"`
KeyID string `json:"kid" yaml:"kid"`
ID int64 `json:"identifier_authz_id" json:"transfer_authz_id" yaml:"id"`
IDTransfer int64 `json:"transfer_authz_id" yaml:"tid"`
Identifier string `json:"identifier" yaml:"identifier"`
Email string `json:"-" yaml:"email,omitempty"`
Expires time.Time `json:"expiration_ts" yaml:"expiration_ts"`
Validated time.Time `json:"validation_ts" yaml:"validation_ts"`
InitURL string `json:"init_url" yaml:"init_url"`
InitURLExpires time.Time `json:"init_url_expiration_ts" yaml:"init_url_expiration_ts"`
Token string `json:"token" yaml:"token"`
Subject string `json:"sub" yaml:"sub"`
KeyID string `json:"kid" yaml:"kid"`
Locale string `json:"locale" yaml:"locale"`
Challenges []Challenge `json:"identifier_challenges" yaml:"identifier_challenges"`
}
// Challenge represents the database and application model for a challenge that is embedded in the IdentityAuthz.
type Challenge struct {
URL string `json:"url" yaml:"url"`
Token string `json:"token" yaml:"token"`
Validated *time.Time `json:"validated" yaml:"validated"`
Token string `json:"token" yaml:"token"`
Identifier string `json:"identifier" yaml:"identifier"`
Status string `json:"status" yaml:"status"`
}
// Identity represents the database and application model for an identity.
......@@ -56,24 +56,9 @@ type Identity struct {
AgentIssuerURL string `json:"agentIssuerURL" yaml:"agentIssuerURL"`
}
type IdentitiesCredentialsResetResponse struct {
URL string `json:"url" yaml:"url"`
ResetExpires int64 `json:"reset_expire" yaml:"urlExpire"`
}
func AuthzFromYamlFile(basepath, id string) (*IdentityAuthz, error) {
filename := fmt.Sprintf(basepath + "/" + id + ".yaml")
b, err := ioutil.ReadFile(filepath.Clean(filename))
if err != nil {
return nil, err
}
authz := new(IdentityAuthz)
err = yaml.Unmarshal(b, authz)
if err != nil {
return nil, err
}
return authz, nil
// Subject represents the database and application model for an subject identity.
type Subject struct {
Subject string `json:"sub" yaml:"sub"`
Identifiers []IdentityAuthzRequest `json:"identifiers" yaml:"identifiers"`
AgentID string `json:"agent_id" yaml:"agentID"`
}
......@@ -10,6 +10,7 @@ import (
yaml "gopkg.in/yaml.v2"
)
// ToYaml marshals the given struct into a slice of bytes
func ToYaml(ia interface{}) ([]byte, error) {
yamlbytes, err := yaml.Marshal(ia)
if err != nil {
......@@ -18,6 +19,7 @@ func ToYaml(ia interface{}) ([]byte, error) {
return yamlbytes, nil
}
// ToYamlFile generic export of struct data to yaml file
func ToYamlFile(ia interface{}, filename string) error {
yamlbytes, err := ToYaml(ia)
......@@ -26,6 +28,7 @@ func ToYamlFile(ia interface{}, filename string) error {
return err
}
defer yf.Close()
_, err = yf.Write(yamlbytes)
if err != nil {
return err
......@@ -33,6 +36,7 @@ func ToYamlFile(ia interface{}, filename string) error {
return nil
}
// FromYamlFile generic import of yaml file data towards the given struct
func FromYamlFile(ia interface{}, filename string) error {
b, err := ioutil.ReadFile(filepath.Clean(filename))
if err != nil {
......@@ -46,38 +50,59 @@ func FromYamlFile(ia interface{}, filename string) error {
return nil
}
func AuthzToYamlFile(ia *models.IdentityAuthz, basepath string) error {
yamlbytes, err := yaml.Marshal(ia)
if err != nil {
return err
}
// SubjectToYamlFile exports subject identity related data to yaml file
func SubjectToYamlFile(sub *models.Subject, basepath string, id string) error {
yf, err := os.OpenFile(basepath+"/"+ia.Identifier+".authz.yaml", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer yf.Close()
_, err = yf.Write(yamlbytes)
if err != nil {
return err
}
return nil
filename := fmt.Sprintf(basepath + "/" + id + ".sub.yaml")
err := ToYamlFile(sub, filename)
return err
}
func AuthzFromYamlFile(basepath, id string) (*models.IdentityAuthz, error) {
filename := fmt.Sprintf(basepath + "/" + id + ".authz.yaml")
// SubjectFromYamlFile imports subject identity data from yaml file
func SubjectFromYamlFile(basepath string, id string) (*models.Subject, error) {
b, err := ioutil.ReadFile(filepath.Clean(filename))
if err != nil {
return nil, err
filename := fmt.Sprintf(basepath + "/" + id + ".sub.yaml")
// import subject data from yaml
subject := new(models.Subject)
err := FromYamlFile(subject, filename)
return subject, err
}
// AuthzToYamlFile exports ongoing identity authz data to yaml file
func AuthzToYamlFile(ia *models.IdentityAuthz, basepath string, isSubject bool) error {
var filename string
// case 1: export recent subject identity related authorization/transfer data
if (isSubject) {
filename = fmt.Sprintf(basepath + "/" + ia.Identifier + ".sub.authz.yaml")
// case 2: export recent general identity related authorization data
} else {
filename = fmt.Sprintf(basepath + "/" + ia.Identifier + ".authz.yaml")
}
// write struct to yaml
err := ToYamlFile(ia, filename)
authz := new(models.IdentityAuthz)
err = yaml.Unmarshal(b, authz)
if err != nil {
return nil, err
return err
}
// AuthzFromYamlFile imports ongoing identity authz data from yaml file
func AuthzFromYamlFile(basepath, id string, isSubject bool) (*models.IdentityAuthz, error) {
var filename string
// case 1: import recent subject identity related authorization/transfer data
if (isSubject) {
filename = fmt.Sprintf(basepath + "/" + id + ".sub.authz.yaml")
// case 2: import recent general identity related authorization data
} else {
filename = fmt.Sprintf(basepath + "/" + id + ".authz.yaml")
}
return authz, nil
// import authz data from yaml
authz := new(models.IdentityAuthz)
err := FromYamlFile(authz, filename)
return authz, err
}
func MakeDirs(dirname string) error {
......