Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
policy
Manage
Activity
Members
Labels
Plan
Issues
4
Issue boards
Milestones
Wiki
Code
Merge requests
2
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Gaia-X
Trust Services API
policy
Commits
6c6ab4f0
Commit
6c6ab4f0
authored
2 years ago
by
Yordan Kinkov
Browse files
Options
Downloads
Patches
Plain Diff
Add extension functions for DID to URL transformation
parent
e451b697
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
cmd/policy/main.go
+3
-0
3 additions, 0 deletions
cmd/policy/main.go
internal/regofunc/did_transformer.go
+145
-0
145 additions, 0 deletions
internal/regofunc/did_transformer.go
internal/regofunc/did_transformer_test.go
+142
-0
142 additions, 0 deletions
internal/regofunc/did_transformer_test.go
with
290 additions
and
0 deletions
cmd/policy/main.go
+
3
−
0
View file @
6c6ab4f0
...
...
@@ -87,6 +87,7 @@ func main() {
taskFuncs
:=
regofunc
.
NewTaskFuncs
(
cfg
.
Task
.
Addr
,
httpClient
)
ocmFuncs
:=
regofunc
.
NewOcmFuncs
(
cfg
.
OCM
.
Addr
,
httpClient
)
signerFuncs
:=
regofunc
.
NewSignerFuncs
(
cfg
.
Signer
.
Addr
,
httpClient
)
didTransformerFuncs
:=
regofunc
.
NewDIDTransformerFuncs
()
regofunc
.
Register
(
"cacheGet"
,
rego
.
Function3
(
cacheFuncs
.
CacheGetFunc
()))
regofunc
.
Register
(
"cacheSet"
,
rego
.
Function4
(
cacheFuncs
.
CacheSetFunc
()))
regofunc
.
Register
(
"didResolve"
,
rego
.
Function1
(
didResolverFuncs
.
ResolveFunc
()))
...
...
@@ -99,6 +100,8 @@ func main() {
regofunc
.
Register
(
"verifyProof"
,
rego
.
Function1
(
signerFuncs
.
VerifyProof
()))
regofunc
.
Register
(
"ocmLoginProofInvitation"
,
rego
.
Function2
(
ocmFuncs
.
GetLoginProofInvitation
()))
regofunc
.
Register
(
"ocmLoginProofResult"
,
rego
.
Function1
(
ocmFuncs
.
GetLoginProofResult
()))
regofunc
.
Register
(
"didToURL"
,
rego
.
Function1
(
didTransformerFuncs
.
ToURLFunc
()))
regofunc
.
Register
(
"urlToDID"
,
rego
.
Function1
(
didTransformerFuncs
.
FromURLFunc
()))
}
// subscribe the cache for policy data changes
...
...
This diff is collapsed.
Click to expand it.
internal/regofunc/did_transformer.go
0 → 100644
+
145
−
0
View file @
6c6ab4f0
package
regofunc
import
(
"fmt"
"net/url"
"strings"
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/types"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/golib/errors"
)
const
(
didSeparator
=
":"
urlSeparator
=
"/"
defaultUrlPath
=
".well-known"
)
type
DIDTransformerFuncs
struct
{}
type
DID
struct
{
scheme
string
// scheme is always "did"
method
string
// method is the specific did method - "web" in this case
path
string
// path is the unique URI assigned by the DID method
}
func
NewDIDTransformerFuncs
()
*
DIDTransformerFuncs
{
return
&
DIDTransformerFuncs
{}
}
func
(
dt
*
DIDTransformerFuncs
)
ToURLFunc
()
(
*
rego
.
Function
,
rego
.
Builtin1
)
{
return
&
rego
.
Function
{
Name
:
"url_from_did"
,
Decl
:
types
.
NewFunction
(
types
.
Args
(
types
.
S
),
types
.
A
),
Memoize
:
true
,
},
func
(
bctx
rego
.
BuiltinContext
,
a
*
ast
.
Term
)
(
*
ast
.
Term
,
error
)
{
var
did
string
if
err
:=
ast
.
As
(
a
.
Value
,
&
did
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid DID: %s"
,
err
)
}
if
did
==
""
{
return
nil
,
errors
.
New
(
"DID cannot be empty"
)
}
u
,
err
:=
dt
.
didToURL
(
did
)
if
err
!=
nil
{
return
nil
,
err
}
return
ast
.
StringTerm
(
u
.
String
()),
nil
}
}
func
(
dt
*
DIDTransformerFuncs
)
FromURLFunc
()
(
*
rego
.
Function
,
rego
.
Builtin1
)
{
return
&
rego
.
Function
{
Name
:
"did_from_url"
,
Decl
:
types
.
NewFunction
(
types
.
Args
(
types
.
S
),
types
.
A
),
Memoize
:
true
,
},
func
(
bctx
rego
.
BuiltinContext
,
a
*
ast
.
Term
)
(
*
ast
.
Term
,
error
)
{
var
u
string
if
err
:=
ast
.
As
(
a
.
Value
,
&
u
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid URL: %s"
,
err
)
}
if
u
==
""
{
return
nil
,
errors
.
New
(
"URL cannot be empty"
)
}
uri
,
err
:=
url
.
Parse
(
u
)
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"cannot parse URL"
)
}
if
uri
.
Host
==
""
||
uri
.
Scheme
!=
"https"
{
return
nil
,
errors
.
New
(
"invalid URL for did:web method"
)
}
did
:=
dt
.
urlToDID
(
uri
)
return
ast
.
StringTerm
(
did
.
String
()),
nil
}
}
// didToURL transforms a valid DID, created by the "did:web" Method Specification, to a URL.
// Documentation can be found here: https://w3c-ccg.github.io/did-method-web/
func
(
dt
*
DIDTransformerFuncs
)
didToURL
(
DID
string
)
(
*
url
.
URL
,
error
)
{
ss
:=
strings
.
Split
(
DID
,
didSeparator
)
if
len
(
ss
)
<
3
{
return
nil
,
errors
.
New
(
"invalid DID, host is not found"
)
}
if
ss
[
0
]
!=
"did"
||
ss
[
1
]
!=
"web"
{
return
nil
,
errors
.
New
(
"invalid DID, method is unknown"
)
}
path
:=
defaultUrlPath
if
len
(
ss
)
>
3
{
path
=
""
for
i
:=
3
;
i
<
len
(
ss
);
i
++
{
path
=
path
+
urlSeparator
+
ss
[
i
]
}
}
path
=
path
+
urlSeparator
+
"did.json"
host
,
err
:=
url
.
PathUnescape
(
ss
[
2
])
if
err
!=
nil
{
return
nil
,
errors
.
New
(
"failed to url decode host from DID"
)
}
return
&
url
.
URL
{
Scheme
:
"https"
,
Host
:
host
,
Path
:
path
,
},
nil
}
// urlToDID transforms a valid URL to a DID created following the "did:web" Method Specification.
// Documentation can be found here: https://w3c-ccg.github.io/did-method-web/
func
(
dt
*
DIDTransformerFuncs
)
urlToDID
(
uri
*
url
.
URL
)
*
DID
{
p
:=
strings
.
TrimRight
(
uri
.
Path
,
"did.json"
)
sp
:=
strings
.
Split
(
p
,
urlSeparator
)
path
:=
url
.
QueryEscape
(
uri
.
Host
)
for
_
,
v
:=
range
sp
{
if
v
==
defaultUrlPath
{
break
}
if
v
==
""
{
continue
}
path
=
path
+
didSeparator
+
url
.
QueryEscape
(
v
)
}
return
&
DID
{
scheme
:
"did"
,
method
:
"web"
,
path
:
strings
.
Trim
(
path
,
didSeparator
),
}
}
// String returns a string representation of this DID.
func
(
d
*
DID
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s:%s:%s"
,
d
.
scheme
,
d
.
method
,
d
.
path
)
}
This diff is collapsed.
Click to expand it.
internal/regofunc/did_transformer_test.go
0 → 100644
+
142
−
0
View file @
6c6ab4f0
package
regofunc_test
import
(
"context"
"encoding/json"
"testing"
"github.com/open-policy-agent/opa/rego"
"github.com/stretchr/testify/assert"
"gitlab.com/gaia-x/data-infrastructure-federation-services/tsa/policy/internal/regofunc"
)
func
TestToURLFunc
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
// test input
name
string
regoQuery
string
// expected result
res
string
errText
string
}{
{
name
:
"DID is empty"
,
regoQuery
:
`url_from_did("")`
,
errText
:
"DID cannot be empty"
,
},
{
name
:
"invalid DID"
,
regoQuery
:
`url_from_did("invalid-did")`
,
errText
:
"invalid DID, host is not found"
,
},
{
name
:
"invalid DID Method"
,
regoQuery
:
`url_from_did("did:sov:123456qwerty")`
,
errText
:
"invalid DID, method is unknown"
,
},
{
name
:
"transformation success with DID containing domain only"
,
regoQuery
:
`url_from_did("did:web:w3c-ccg.github.io")`
,
res
:
"
\"
https://w3c-ccg.github.io/.well-known/did.json
\"
"
,
},
{
name
:
"transformation success with DID containing domain and path"
,
regoQuery
:
`url_from_did("did:web:w3c-ccg.github.io:user:alice")`
,
res
:
"
\"
https://w3c-ccg.github.io/user/alice/did.json
\"
"
,
},
{
name
:
"transformation success with DID containing network port"
,
regoQuery
:
`url_from_did("did:web:example.com%3A3000:user:alice")`
,
res
:
"
\"
https://example.com:3000/user/alice/did.json
\"
"
,
},
}
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
DIDTransformerFuncs
:=
regofunc
.
NewDIDTransformerFuncs
()
r
:=
rego
.
New
(
rego
.
Query
(
test
.
regoQuery
),
rego
.
Function1
(
DIDTransformerFuncs
.
ToURLFunc
()),
rego
.
StrictBuiltinErrors
(
true
),
)
resultSet
,
err
:=
r
.
Eval
(
context
.
Background
())
if
err
==
nil
{
resultBytes
,
err
:=
json
.
Marshal
(
resultSet
[
0
]
.
Expressions
[
0
]
.
Value
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
test
.
res
,
string
(
resultBytes
))
}
else
{
assert
.
ErrorContains
(
t
,
err
,
test
.
errText
)
}
})
}
}
func
TestFromURLFunc
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
// test input
name
string
regoQuery
string
// expected result
res
string
errText
string
}{
{
name
:
"empty URL"
,
regoQuery
:
`did_from_url("")`
,
errText
:
"URL cannot be empty"
,
},
{
name
:
"URL containing special characters"
,
regoQuery
:
`did_from_url("example.com\nH1234")`
,
errText
:
"cannot parse URL"
,
},
{
name
:
"URL does not contain secure protocol (https)"
,
regoQuery
:
`did_from_url("example.com")`
,
errText
:
"invalid URL for did:web method"
,
},
{
name
:
"URL does not contain valid domain"
,
regoQuery
:
`did_from_url("https://")`
,
errText
:
"invalid URL for did:web method"
,
},
{
name
:
"transformation success with URL containing domain only"
,
regoQuery
:
`did_from_url("https://w3c-ccg.github.io/.well-known/did.json")`
,
res
:
"
\"
did:web:w3c-ccg.github.io
\"
"
,
},
{
name
:
"transformation success with URL containing domain with path"
,
regoQuery
:
`did_from_url("https://w3c-ccg.github.io/user/alice/did.json")`
,
res
:
"
\"
did:web:w3c-ccg.github.io:user:alice
\"
"
,
},
{
name
:
"transformation success with URL containing network port"
,
regoQuery
:
`did_from_url("https://example.com:3000/user/alice/did.json")`
,
res
:
"
\"
did:web:example.com%3A3000:user:alice
\"
"
,
},
}
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
DIDTransformerFuncs
:=
regofunc
.
NewDIDTransformerFuncs
()
r
:=
rego
.
New
(
rego
.
Query
(
test
.
regoQuery
),
rego
.
Function1
(
DIDTransformerFuncs
.
FromURLFunc
()),
rego
.
StrictBuiltinErrors
(
true
),
)
resultSet
,
err
:=
r
.
Eval
(
context
.
Background
())
if
err
==
nil
{
resultBytes
,
err
:=
json
.
Marshal
(
resultSet
[
0
]
.
Expressions
[
0
]
.
Value
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
test
.
res
,
string
(
resultBytes
))
}
else
{
assert
.
ErrorContains
(
t
,
err
,
test
.
errText
)
}
})
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment