From 01f7976f526e5ae79299fab851af09d99148e4ee Mon Sep 17 00:00:00 2001 From: Henry Avetisyan Date: Sun, 21 Oct 2018 16:54:07 -0700 Subject: [PATCH] extra options for meta only signed domain list --- clients/go/zms/client.go | 4 +- clients/go/zms/model.go | 10 + clients/go/zms/zms_schema.go | 3 + .../java/com/yahoo/athenz/zms/ZMSClient.java | 35 ++- .../athenz/zms/ZMSRDLGeneratedClient.java | 5 +- .../com/yahoo/athenz/zms/ZMSClientTest.java | 2 +- .../com/yahoo/athenz/zms/DomainModified.java | 27 ++ .../java/com/yahoo/athenz/zms/ZMSSchema.java | 5 +- core/zms/src/main/rdl/SignedDomains.rdli | 5 +- .../com/yahoo/athenz/zms/ZMSCoreTest.java | 161 +++++++++- libs/go/zmscli/domain.go | 4 +- .../java/com/yahoo/athenz/zms/ZMSHandler.java | 2 +- .../java/com/yahoo/athenz/zms/ZMSImpl.java | 124 ++++++-- .../com/yahoo/athenz/zms/ZMSResources.java | 4 +- .../athenz/zms/store/file/FileConnection.java | 23 +- .../athenz/zms/store/jdbc/JDBCConnection.java | 8 +- .../com/yahoo/athenz/zms/utils/ZMSUtils.java | 8 + .../yahoo/athenz/zms/ExceptionMapperTest.java | 45 +++ .../com/yahoo/athenz/zms/ZMSImplTest.java | 294 +++++++++++++++--- .../impl/JDBCCertRecordStoreFactoryTest.java | 42 +++ .../zms/store/jdbc/JDBCConnectionTest.java | 4 + .../yahoo/athenz/zms/utils/ZMSUtilsTest.java | 11 + 22 files changed, 724 insertions(+), 102 deletions(-) create mode 100644 servers/zms/src/test/java/com/yahoo/athenz/zms/ExceptionMapperTest.java create mode 100644 servers/zms/src/test/java/com/yahoo/athenz/zms/store/impl/JDBCCertRecordStoreFactoryTest.java diff --git a/clients/go/zms/client.go b/clients/go/zms/client.go index 3880c9387b2..22b34f288f3 100644 --- a/clients/go/zms/client.go +++ b/clients/go/zms/client.go @@ -2210,12 +2210,12 @@ func (client ZMSClient) GetResourceAccessList(principal EntityName, action Actio } } -func (client ZMSClient) GetSignedDomains(domain DomainName, metaOnly string, matchingTag string) (*SignedDomains, string, error) { +func (client ZMSClient) GetSignedDomains(domain DomainName, metaOnly string, metaAttr SimpleName, matchingTag string) (*SignedDomains, string, error) { var data *SignedDomains headers := map[string]string{ "If-None-Match": matchingTag, } - url := client.URL + "/sys/modified_domains" + encodeParams(encodeStringParam("domain", string(domain), ""), encodeStringParam("metaonly", string(metaOnly), "")) + url := client.URL + "/sys/modified_domains" + encodeParams(encodeStringParam("domain", string(domain), ""), encodeStringParam("metaonly", string(metaOnly), ""), encodeStringParam("metaattr", string(metaAttr), "")) resp, err := client.httpGet(url, headers) if err != nil { return nil, "", err diff --git a/clients/go/zms/model.go b/clients/go/zms/model.go index 089d65c5b64..fa9c4190ef2 100644 --- a/clients/go/zms/model.go +++ b/clients/go/zms/model.go @@ -3153,6 +3153,16 @@ type DomainModified struct { // last modified timestamp of the domain // Modified int64 `json:"modified"` + + // + // associated cloud (i.e. aws) account id + // + Account string `json:"account,omitempty" rdl:"optional"` + + // + // associated product id + // + YpmId *int32 `json:"ypmId,omitempty" rdl:"optional"` } // diff --git a/clients/go/zms/zms_schema.go b/clients/go/zms/zms_schema.go index 5d4f335fa74..3261f1c1c3b 100644 --- a/clients/go/zms/zms_schema.go +++ b/clients/go/zms/zms_schema.go @@ -350,6 +350,8 @@ func init() { tDomainModified.Comment("Tuple of domain-name and modification time-stamps. This object is returned when the caller has requested list of domains modified since a specific timestamp.") tDomainModified.Field("name", "DomainName", false, nil, "name of the domain") tDomainModified.Field("modified", "Int64", false, nil, "last modified timestamp of the domain") + tDomainModified.Field("account", "String", true, nil, "associated cloud (i.e. aws) account id") + tDomainModified.Field("ypmId", "Int32", true, nil, "associated product id") sb.AddType(tDomainModified.Build()) tDomainModifiedList := rdl.NewStructTypeBuilder("Struct", "DomainModifiedList") @@ -1204,6 +1206,7 @@ func init() { mGetSignedDomains.Comment("Retrieve the list of modified domains since the specified timestamp. The server will return the list of all modified domains and the latest modification timestamp as the value of the ETag header. The client will need to use this value during its next call to request the changes since the previous request. When metaonly set to true, dont add roles, policies or services, dont sign") mGetSignedDomains.Input("domain", "DomainName", false, "domain", "", true, nil, "filter the domain list only to the specified name") mGetSignedDomains.Input("metaOnly", "String", false, "metaonly", "", true, nil, "valid values are \"true\" or \"false\"") + mGetSignedDomains.Input("metaAttr", "SimpleName", false, "metaattr", "", true, nil, "domain meta attribute to filter/return, valid values \"account\", \"ypmId\", or \"all\"") mGetSignedDomains.Input("matchingTag", "String", false, "", "If-None-Match", false, nil, "Retrieved from the previous request, this timestamp specifies to the server to return any domains modified since this time") mGetSignedDomains.Output("tag", "String", "ETag", false, "The current latest modification timestamp is returned in this header") mGetSignedDomains.Auth("", "", true, "") diff --git a/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSClient.java b/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSClient.java index 94115dfe6a1..8af6fde1d53 100644 --- a/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSClient.java +++ b/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSClient.java @@ -1544,16 +1544,47 @@ public Access getAccessExt(String action, String resource, String trustDomain, S */ public SignedDomains getSignedDomains(String domainName, String metaOnly, String matchingTag, Map> responseHeaders) { + return getSignedDomains(domainName, metaOnly, null, matchingTag, responseHeaders); + } + + /** + * Retrieve the list of all domain data from the ZMS Server that + * is signed with ZMS's private key. It will pass an optional matchingTag + * so that ZMS can skip returning domains if no changes have taken + * place since that tag was issued. + * @param domainName name of the domain. if specified, the server will + * only return this domain in the result set + * @param metaOnly (can be null) must have value of true or false (default). + * if set to true, zms server will only return meta information + * about each domain (description, last modified timestamp, etc) and + * no role/policy/service details will be returned. + * @param metaAttr (can be null) if metaOnly option is set to true, this + * parameter can filter the results based on the presence of the + * requested attribute. Allowed values are: account, ypmid, and all. + * account - only return domains that have the account value set + * ypmid - only return domains that have the ypmid value set + * all - return all domains (no filtering). + * @param matchingTag (can be null) contains modified timestamp received + * with last request. If null, then return all domains. + * @param responseHeaders contains the "tag" returned for modification + * time of the domains, map key = "tag", List should + * contain a single value timestamp String to be used + * with subsequent call as matchingTag to this API + * @return list of domains signed by ZMS Server + * @throws ZMSClientException in case of failure + */ + public SignedDomains getSignedDomains(String domainName, String metaOnly, String metaAttr, + String matchingTag, Map> responseHeaders) { updatePrincipal(); try { - return client.getSignedDomains(domainName, metaOnly, matchingTag, responseHeaders); + return client.getSignedDomains(domainName, metaOnly, metaAttr, matchingTag, responseHeaders); } catch (ResourceException ex) { throw new ZMSClientException(ex.getCode(), ex.getData()); } catch (Exception ex) { throw new ZMSClientException(ZMSClientException.BAD_REQUEST, ex.getMessage()); } } - + /** * For the specified user credentials return the corresponding User Token that * can be used for authenticating other ZMS operations. The client internally diff --git a/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSRDLGeneratedClient.java b/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSRDLGeneratedClient.java index 70d69cea2f5..8f1c2c7e703 100644 --- a/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSRDLGeneratedClient.java +++ b/clients/java/zms/src/main/java/com/yahoo/athenz/zms/ZMSRDLGeneratedClient.java @@ -1301,7 +1301,7 @@ public ResourceAccessList getResourceAccessList(String principal, String action) } - public SignedDomains getSignedDomains(String domain, String metaOnly, String matchingTag, java.util.Map> headers) { + public SignedDomains getSignedDomains(String domain, String metaOnly, String metaAttr, String matchingTag, java.util.Map> headers) { WebTarget target = base.path("/sys/modified_domains"); if (domain != null) { target = target.queryParam("domain", domain); @@ -1309,6 +1309,9 @@ public SignedDomains getSignedDomains(String domain, String metaOnly, String mat if (metaOnly != null) { target = target.queryParam("metaonly", metaOnly); } + if (metaAttr != null) { + target = target.queryParam("metaattr", metaAttr); + } Invocation.Builder invocationBuilder = target.request("application/json"); if (credsHeader != null) { invocationBuilder = credsHeader.startsWith("Cookie.") ? invocationBuilder.cookie(credsHeader.substring(7), diff --git a/clients/java/zms/src/test/java/com/yahoo/athenz/zms/ZMSClientTest.java b/clients/java/zms/src/test/java/com/yahoo/athenz/zms/ZMSClientTest.java index f16440ccb2f..df07cbea3f6 100644 --- a/clients/java/zms/src/test/java/com/yahoo/athenz/zms/ZMSClientTest.java +++ b/clients/java/zms/src/test/java/com/yahoo/athenz/zms/ZMSClientTest.java @@ -1543,7 +1543,7 @@ public void testGetSignedDomains() { client.setZMSRDLGeneratedClient(c); Map> respHdrs = new HashMap<>(); SignedDomains signedDomain1 = Mockito.mock(SignedDomains.class); - Mockito.when(c.getSignedDomains("dom1", "meta1", "tag1", respHdrs)).thenReturn(signedDomain1).thenThrow(new ZMSClientException(400,"Audit reference required")); + Mockito.when(c.getSignedDomains("dom1", "meta1", null, "tag1", respHdrs)).thenReturn(signedDomain1).thenThrow(new ZMSClientException(400,"Audit reference required")); client.getSignedDomains("dom1", "meta1", "tag1", respHdrs); try { client.getSignedDomains("dom1", "meta1", "tag1", respHdrs); diff --git a/core/zms/src/main/java/com/yahoo/athenz/zms/DomainModified.java b/core/zms/src/main/java/com/yahoo/athenz/zms/DomainModified.java index 1250654ad27..b0ab3fcf8b9 100644 --- a/core/zms/src/main/java/com/yahoo/athenz/zms/DomainModified.java +++ b/core/zms/src/main/java/com/yahoo/athenz/zms/DomainModified.java @@ -3,6 +3,7 @@ // package com.yahoo.athenz.zms; +import com.fasterxml.jackson.annotation.JsonInclude; import com.yahoo.rdl.*; // @@ -13,6 +14,12 @@ public class DomainModified { public String name; public long modified; + @RdlOptional + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public String account; + @RdlOptional + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Integer ypmId; public DomainModified setName(String name) { this.name = name; @@ -28,6 +35,20 @@ public DomainModified setModified(long modified) { public long getModified() { return modified; } + public DomainModified setAccount(String account) { + this.account = account; + return this; + } + public String getAccount() { + return account; + } + public DomainModified setYpmId(Integer ypmId) { + this.ypmId = ypmId; + return this; + } + public Integer getYpmId() { + return ypmId; + } @Override public boolean equals(Object another) { @@ -42,6 +63,12 @@ public boolean equals(Object another) { if (modified != a.modified) { return false; } + if (account == null ? a.account != null : !account.equals(a.account)) { + return false; + } + if (ypmId == null ? a.ypmId != null : !ypmId.equals(a.ypmId)) { + return false; + } } return true; } diff --git a/core/zms/src/main/java/com/yahoo/athenz/zms/ZMSSchema.java b/core/zms/src/main/java/com/yahoo/athenz/zms/ZMSSchema.java index 2ab001ac8b9..16d29d4afab 100644 --- a/core/zms/src/main/java/com/yahoo/athenz/zms/ZMSSchema.java +++ b/core/zms/src/main/java/com/yahoo/athenz/zms/ZMSSchema.java @@ -297,7 +297,9 @@ private static Schema build() { sb.structType("DomainModified") .comment("Tuple of domain-name and modification time-stamps. This object is returned when the caller has requested list of domains modified since a specific timestamp.") .field("name", "DomainName", false, "name of the domain") - .field("modified", "Int64", false, "last modified timestamp of the domain"); + .field("modified", "Int64", false, "last modified timestamp of the domain") + .field("account", "String", true, "associated cloud (i.e. aws) account id") + .field("ypmId", "Int32", true, "associated product id"); sb.structType("DomainModifiedList") .comment("A list of {domain, modified-timestamp} tuples.") @@ -1399,6 +1401,7 @@ private static Schema build() { .comment("Retrieve the list of modified domains since the specified timestamp. The server will return the list of all modified domains and the latest modification timestamp as the value of the ETag header. The client will need to use this value during its next call to request the changes since the previous request. When metaonly set to true, dont add roles, policies or services, dont sign") .queryParam("domain", "domain", "DomainName", null, "filter the domain list only to the specified name") .queryParam("metaonly", "metaOnly", "String", null, "valid values are \"true\" or \"false\"") + .queryParam("metaattr", "metaAttr", "SimpleName", null, "domain meta attribute to filter/return, valid values \"account\", \"ypmId\", or \"all\"") .headerParam("If-None-Match", "matchingTag", "String", null, "Retrieved from the previous request, this timestamp specifies to the server to return any domains modified since this time") .output("ETag", "tag", "String", "The current latest modification timestamp is returned in this header") .auth("", "", true) diff --git a/core/zms/src/main/rdl/SignedDomains.rdli b/core/zms/src/main/rdl/SignedDomains.rdli index df511a25cd0..dd2cf87da1a 100644 --- a/core/zms/src/main/rdl/SignedDomains.rdli +++ b/core/zms/src/main/rdl/SignedDomains.rdli @@ -11,6 +11,8 @@ include "Entity.tdl"; type DomainModified Struct { DomainName name; //name of the domain Int64 modified; //last modified timestamp of the domain + String account (optional); //associated cloud (i.e. aws) account id + Int32 ypmId (optional); //associated product id } //A list of {domain, modified-timestamp} tuples. @@ -68,9 +70,10 @@ type SignedDomains Struct { //timestamp as the value of the ETag header. The client will need to use this //value during its next call to request the changes since the previous request. // When metaonly set to true, dont add roles, policies or services, dont sign -resource SignedDomains GET "/sys/modified_domains?domain={domain}&metaonly={metaOnly}" { +resource SignedDomains GET "/sys/modified_domains?domain={domain}&metaonly={metaOnly}&metaattr={metaAttr}" { DomainName domain (optional); //filter the domain list only to the specified name String metaOnly (optional); // valid values are "true" or "false" + SimpleName metaAttr (optional); // domain meta attribute to filter/return, valid values "account", "ypmId", or "all" String matchingTag (header="If-None-Match"); //Retrieved from the previous request, this timestamp specifies to the server to return any domains modified since this time String tag (header="ETag", out); //The current latest modification timestamp is returned in this header authenticate; diff --git a/core/zms/src/test/java/com/yahoo/athenz/zms/ZMSCoreTest.java b/core/zms/src/test/java/com/yahoo/athenz/zms/ZMSCoreTest.java index 97bca80a352..d462969a2b4 100644 --- a/core/zms/src/test/java/com/yahoo/athenz/zms/ZMSCoreTest.java +++ b/core/zms/src/test/java/com/yahoo/athenz/zms/ZMSCoreTest.java @@ -888,27 +888,180 @@ public void testUserDomainMethod() { assertFalse(ud.equals(new String())); } + @Test + public void testRoleMember() { + + Schema schema = ZMSSchema.instance(); + Validator validator = new Validator(schema); + + RoleMember rm = new RoleMember().setMemberName("user.test1").setExpiration(Timestamp.fromMillis(123456789123L)); + assertTrue(rm.equals(rm)); + + Result result = validator.validate(rm, "RoleMember"); + assertTrue(result.valid); + + assertEquals(rm.getMemberName(), "user.test1"); + assertEquals(rm.getExpiration().millis(), 123456789123L); + + RoleMember rm2 = new RoleMember().setMemberName("user.test2"); + assertFalse(rm2.equals(rm)); + + rm2.setMemberName("user.test1"); + assertFalse(rm2.equals(rm)); + + rm2.setExpiration(Timestamp.fromMillis(123456789124L)); + assertFalse(rm2.equals(rm)); + rm2.setExpiration(Timestamp.fromMillis(123456789123L)); + assertTrue(rm2.equals(rm)); + + assertFalse(rm2.equals(null)); + } + + @Test + public void testStatus() { + + Schema schema = ZMSSchema.instance(); + Validator validator = new Validator(schema); + + Status st = new Status().setCode(101).setMessage("ok"); + assertTrue(st.equals(st)); + + Result result = validator.validate(st, "Status"); + assertTrue(result.valid); + + assertEquals(st.getCode(), 101); + assertEquals(st.getMessage(), "ok"); + + Status st2 = new Status().setCode(1020); + assertFalse(st2.equals(st)); + + st2.setCode(101); + assertFalse(st2.equals(st)); + + st2.setMessage("failed"); + assertFalse(st2.equals(st)); + st2.setMessage("ok"); + assertTrue(st2.equals(st)); + + assertFalse(st2.equals(null)); + } + + @Test + public void testTemplateParam() { + + Schema schema = ZMSSchema.instance(); + Validator validator = new Validator(schema); + + TemplateParam tp = new TemplateParam().setName("name").setValue("service"); + assertTrue(tp.equals(tp)); + + Result result = validator.validate(tp, "TemplateParam"); + assertTrue(result.valid); + + assertEquals(tp.getName(), "name"); + assertEquals(tp.getValue(), "service"); + + TemplateParam tp2 = new TemplateParam().setName("name2"); + assertFalse(tp2.equals(tp)); + + tp2.setName("name"); + assertFalse(tp2.equals(tp)); + + tp2.setValue("value2"); + assertFalse(tp2.equals(tp)); + tp2.setValue("service"); + assertTrue(tp2.equals(tp)); + + assertFalse(tp2.equals(null)); + } + + @Test + public void testTenancyResourceGroup() { + + Schema schema = ZMSSchema.instance(); + Validator validator = new Validator(schema); + + TenancyResourceGroup tp = new TenancyResourceGroup().setDomain("dom1") + .setResourceGroup("rg1").setService("svc1"); + assertTrue(tp.equals(tp)); + + assertEquals(tp.getDomain(), "dom1"); + assertEquals(tp.getResourceGroup(), "rg1"); + assertEquals(tp.getService(), "svc1"); + + TenancyResourceGroup tp2 = new TenancyResourceGroup().setDomain("dom2"); + assertFalse(tp2.equals(tp)); + + tp2.setDomain("dom1"); + assertFalse(tp2.equals(tp)); + + tp2.setService("svc2"); + assertFalse(tp2.equals(tp)); + tp2.setService("svc1"); + assertFalse(tp2.equals(tp)); + + tp2.setResourceGroup("rg2"); + assertFalse(tp2.equals(tp)); + tp2.setResourceGroup("rg1"); + assertTrue((tp2.equals(tp))); + + assertFalse(tp2.equals(null)); + } + + @Test + public void testUserMeta() { + + UserMeta um = new UserMeta().setEnabled(false); + assertTrue(um.equals(um)); + + assertEquals(um.getEnabled(), Boolean.FALSE); + + UserMeta um2 = new UserMeta().init(); + assertFalse(um2.equals(um)); + + um2.setEnabled(false); + assertEquals(um2, um); + assertFalse(um2.equals(null)); + } + @Test public void testDomainModifiedListMethod() { Schema schema = ZMSSchema.instance(); Validator validator = new Validator(schema); // DomainModified test - DomainModified dm = new DomainModified().setName("test.domain").setModified(123456789123L); + DomainModified dm = new DomainModified().setName("test.domain") + .setModified(123456789123L) + .setAccount("1234") + .setYpmId(1001); + assertTrue(dm.equals(dm)); Result result = validator.validate(dm, "DomainModified"); assertTrue(result.valid); assertEquals(dm.getName(), "test.domain"); assertEquals(dm.getModified(), 123456789123L); + assertEquals(dm.getAccount(), "1234"); + assertEquals(dm.getYpmId().intValue(), 1001); DomainModified dm2 = new DomainModified().setName("test.domain"); - assertTrue(dm.equals(dm)); - + assertFalse(dm2.equals(dm)); + dm2.setModified(123456789124L); assertFalse(dm2.equals(dm)); - dm2.setName(null); + dm2.setModified(123456789123L); + assertFalse(dm2.equals(dm)); + + dm2.setAccount("1235"); assertFalse(dm2.equals(dm)); + dm2.setAccount("1234"); + assertFalse(dm2.equals(dm)); + + dm2.setYpmId(1002); + assertFalse(dm2.equals(dm)); + dm2.setYpmId(1001); + assertTrue(dm2.equals(dm)); + assertFalse(dm2.equals(null)); // DomainModifiedList test diff --git a/libs/go/zmscli/domain.go b/libs/go/zmscli/domain.go index 72a8a269a9c..d0a346f5224 100644 --- a/libs/go/zmscli/domain.go +++ b/libs/go/zmscli/domain.go @@ -341,7 +341,7 @@ func (cli Zms) ListDomains(limit *int32, skip string, prefix string, depth *int3 func (cli Zms) GetSignedDomains(dn string, matchingTag string) (*string, error) { var buf bytes.Buffer - res, etag, err := cli.Zms.GetSignedDomains(zms.DomainName(dn), "false", matchingTag) + res, etag, err := cli.Zms.GetSignedDomains(zms.DomainName(dn), "false", "", matchingTag) if err != nil { return nil, err } @@ -366,7 +366,7 @@ func (cli Zms) ShowDomain(dn string) (*string, error) { cli.dumpDomain(&buf, domain) // now retrieve the full domain in one call - res, _, err := cli.Zms.GetSignedDomains(zms.DomainName(dn), "false", "") + res, _, err := cli.Zms.GetSignedDomains(zms.DomainName(dn), "false", "", "") if err != nil { return nil, err } diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSHandler.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSHandler.java index 9459bcbb374..10a1df486b3 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSHandler.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSHandler.java @@ -66,7 +66,7 @@ public interface ZMSHandler { Access getAccess(ResourceContext context, String action, String resource, String domain, String checkPrincipal); Access getAccessExt(ResourceContext context, String action, String resource, String domain, String checkPrincipal); ResourceAccessList getResourceAccessList(ResourceContext context, String principal, String action); - Response getSignedDomains(ResourceContext context, String domain, String metaOnly, String matchingTag); + Response getSignedDomains(ResourceContext context, String domain, String metaOnly, String metaAttr, String matchingTag); UserToken getUserToken(ResourceContext context, String userName, String serviceNames, Boolean header); UserToken optionsUserToken(ResourceContext context, String userName, String serviceNames); ServicePrincipal getServicePrincipal(ResourceContext context); diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java index 5454b3a3293..303c0f79685 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java @@ -99,7 +99,11 @@ public class ZMSImpl implements Authorizer, KeyStore, ZMSHandler { private static final String TEMPLATE_FIELD = "template"; private static final String META_FIELD = "meta"; private static final String DOMAIN_FIELD = "domain"; - + + private static final String META_ATTR_ACCOUNT = "account"; + private static final String META_ATTR_YPM_ID = "ypmid"; + private static final String META_ATTR_ALL = "all"; + private static final String SYS_AUTH = "sys.auth"; private static final String USER_TOKEN_DEFAULT_NAME = "_self_"; @@ -4036,26 +4040,83 @@ long getModTimestamp(String matchingTag) { return timestamp; } - - SignedDomain retrieveSignedDomain(String domainName, long modifiedTime, - Boolean setMetaDataOnly) { - - // generate our signed domain object - + + SignedDomain createSignedDomain(String domainName, long modifiedTime) { SignedDomain signedDomain = new SignedDomain(); DomainData domainData = new DomainData().setName(domainName); signedDomain.setDomain(domainData); domainData.setModified(Timestamp.fromMillis(modifiedTime)); - + return signedDomain; + } + + SignedDomain retrieveSignedDomainMeta(final String domainName, long modifiedTime, + final String account, Integer ypmId, final String metaAttr) { + + SignedDomain signedDomain = createSignedDomain(domainName, modifiedTime); + if (metaAttr != null) { + switch (metaAttr) { + case META_ATTR_ACCOUNT: + if (account == null) { + return null; + } + signedDomain.getDomain().setAccount(account); + break; + case META_ATTR_YPM_ID: + if (ypmId == null) { + return null; + } + signedDomain.getDomain().setYpmId(ypmId); + break; + case META_ATTR_ALL: + signedDomain.getDomain().setAccount(account); + signedDomain.getDomain().setYpmId(ypmId); + break; + } + } + return signedDomain; + } + + SignedDomain retrieveSignedDomain(Domain domain, final String metaAttr, boolean setMetaDataOnly) { + // check if we're asked to only return the meta data which // we already have - name and last modified time, so we can // add the domain to our return list and continue with the // next domain - + + SignedDomain signedDomain; if (setMetaDataOnly) { - return signedDomain; + signedDomain = retrieveSignedDomainMeta(domain.getName(), domain.getModified().millis(), + domain.getAccount(), domain.getYpmId(), metaAttr); + } else { + signedDomain = retrieveSignedDomainData(domain.getName(), domain.getModified().millis()); } - + return signedDomain; + } + + SignedDomain retrieveSignedDomain(DomainModified domainModified, final String metaAttr, + boolean setMetaDataOnly) { + + // check if we're asked to only return the meta data which + // we already have - name and last modified time, so we can + // add the domain to our return list and continue with the + // next domain + + SignedDomain signedDomain; + if (setMetaDataOnly) { + signedDomain = retrieveSignedDomainMeta(domainModified.getName(), domainModified.getModified(), + domainModified.getAccount(), domainModified.getYpmId(), metaAttr); + } else { + signedDomain = retrieveSignedDomainData(domainModified.getName(), domainModified.getModified()); + } + return signedDomain; + } + + SignedDomain retrieveSignedDomainData(final String domainName, long modifiedTime) { + + // generate our signed domain object + + SignedDomain signedDomain = createSignedDomain(domainName, modifiedTime); + // get the policies, roles, and service identities to create the // DomainData @@ -4075,9 +4136,12 @@ SignedDomain retrieveSignedDomain(String domainName, long modifiedTime, // set domain attributes - for enabled flag only set it // if it set to false - - if (athenzDomain.getDomain().getEnabled() == Boolean.FALSE) { - domainData.setEnabled(athenzDomain.getDomain().getEnabled()); + + DomainData domainData = signedDomain.getDomain(); + + Boolean enabled = athenzDomain.getDomain().getEnabled(); + if (enabled == Boolean.FALSE) { + domainData.setEnabled(enabled); } domainData.setAccount(athenzDomain.getDomain().getAccount()); domainData.setYpmId(athenzDomain.getDomain().getYpmId()); @@ -4096,18 +4160,18 @@ SignedDomain retrieveSignedDomain(String domainName, long modifiedTime, domainData.setPolicies(signedPolicies); String signature = Crypto.sign( - SignUtils.asCanonicalString(signedDomain.getDomain().getPolicies().getContents()), privateKey); - signedDomain.getDomain().getPolicies().setSignature(signature).setKeyId(privateKeyId); + SignUtils.asCanonicalString(signedPolicies.getContents()), privateKey); + signedPolicies.setSignature(signature).setKeyId(privateKeyId); // then sign the data and set the data and signature in a SignedDomain - signature = Crypto.sign(SignUtils.asCanonicalString(signedDomain.getDomain()), privateKey); + signature = Crypto.sign(SignUtils.asCanonicalString(domainData), privateKey); signedDomain.setSignature(signature).setKeyId(privateKeyId); return signedDomain; } public Response getSignedDomains(ResourceContext ctx, String domainName, String metaOnly, - String matchingTag) { + String metaAttr, String matchingTag) { final String caller = "getsigneddomains"; metric.increment(ZMSConsts.HTTP_GET); @@ -4124,18 +4188,14 @@ public Response getSignedDomains(ResourceContext ctx, String domainName, String if (domainName != null) { domainName = domainName.toLowerCase(); + validate(domainName, TYPE_DOMAIN_NAME, caller); } - - boolean setMetaDataOnly = false; - if (metaOnly != null) { - - if (LOG.isDebugEnabled()) { - LOG.debug("getSignedDomains: metaonly: {}", metaOnly); - } - - setMetaDataOnly = Boolean.parseBoolean(metaOnly.trim()); + if (metaAttr != null) { + metaAttr = metaAttr.toLowerCase(); + validate(metaAttr, TYPE_SIMPLE_NAME, caller); } + boolean setMetaDataOnly = ZMSUtils.parseBoolean(metaOnly, false); long timestamp = getModTimestamp(matchingTag); // if this is one of our system principals then we're going to @@ -4164,10 +4224,10 @@ public Response getSignedDomains(ResourceContext ctx, String domainName, String throw ex; } } - + if (domain != null) { youngestDomMod = domain.getModified().millis(); - + if (timestamp != 0 && youngestDomMod <= timestamp) { EntityTag eTag = new EntityTag(domain.getModified().toString()); return Response.status(ResourceException.NOT_MODIFIED) @@ -4176,8 +4236,7 @@ public Response getSignedDomains(ResourceContext ctx, String domainName, String // generate our signed domain object - SignedDomain signedDomain = retrieveSignedDomain(domainName, youngestDomMod, - setMetaDataOnly); + SignedDomain signedDomain = retrieveSignedDomain(domain, metaAttr, setMetaDataOnly); if (signedDomain != null) { sdList.add(signedDomain); @@ -4225,8 +4284,7 @@ public Response getSignedDomains(ResourceContext ctx, String domainName, String // generate our signed domain object - SignedDomain signedDomain = retrieveSignedDomain(dmod.getName(), dmod.getModified(), - setMetaDataOnly); + SignedDomain signedDomain = retrieveSignedDomain(dmod, metaAttr, setMetaDataOnly); // it's possible that our domain was deleted by another // thread while we were processing this request so diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSResources.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSResources.java index 4312b715d34..6453023f1db 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSResources.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSResources.java @@ -1573,11 +1573,11 @@ public ResourceAccessList getResourceAccessList(@QueryParam("principal") String @GET @Path("/sys/modified_domains") @Produces(MediaType.APPLICATION_JSON) - public Response getSignedDomains(@QueryParam("domain") String domain, @QueryParam("metaonly") String metaOnly, @HeaderParam("If-None-Match") String matchingTag) { + public Response getSignedDomains(@QueryParam("domain") String domain, @QueryParam("metaonly") String metaOnly, @QueryParam("metaattr") String metaAttr, @HeaderParam("If-None-Match") String matchingTag) { try { ResourceContext context = this.delegate.newResourceContext(this.request, this.response); context.authenticate(); - return this.delegate.getSignedDomains(context, domain, metaOnly, matchingTag); + return this.delegate.getSignedDomains(context, domain, metaOnly, metaAttr, matchingTag); } catch (ResourceException e) { int code = e.getCode(); switch (code) { diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/store/file/FileConnection.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/store/file/FileConnection.java index b047b98bdb4..b803acd5825 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/store/file/FileConnection.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/store/file/FileConnection.java @@ -357,20 +357,19 @@ public DomainModifiedList listModifiedDomains(long modifiedSince) { // Now set the dest for the returned domain names - String dirName = rootDir.getAbsolutePath() + File.separator; for (String dname : domainList) { - long ts = 0; - try { - File dfile = new File(dirName + dname); - ts = dfile.lastModified(); - if (ts <= modifiedSince) { - continue; - } - } catch (Exception exc) { - LOG.error("FileStructStore: FAILED to get timestamp for file " - + dname + ", error: " + exc.getMessage()); + DomainStruct domainStruct = getDomainStruct(dname); + if (domainStruct == null) { + return null; + } + long ts = domainStruct.getModified().millis(); + if (ts <= modifiedSince) { + continue; } - DomainModified dm = new DomainModified().setName(dname).setModified(ts); + DomainModified dm = new DomainModified().setName(dname) + .setModified(ts) + .setYpmId(domainStruct.getMeta().getYpmId()) + .setAccount(domainStruct.getMeta().getAccount()); nameMods.add(dm); } diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnection.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnection.java index 4d77c414c18..3653fec7dd9 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnection.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnection.java @@ -81,9 +81,9 @@ public class JDBCConnection implements ObjectStoreConnection { private static final String SQL_UPDATE_DOMAIN_MOD_TIMESTAMP = "UPDATE domain " + "SET modified=CURRENT_TIMESTAMP(3) WHERE name=?;"; private static final String SQL_GET_DOMAIN_MOD_TIMESTAMP = "SELECT modified FROM domain WHERE name=?;"; - private static final String SQL_LIST_DOMAIN = "SELECT name, modified FROM domain;"; + private static final String SQL_LIST_DOMAIN = "SELECT name, modified, account, ypm_id FROM domain;"; private static final String SQL_LIST_DOMAIN_PREFIX = "SELECT name, modified FROM domain WHERE name>=? AND name?;"; + private static final String SQL_LIST_DOMAIN_MODIFIED = "SELECT name, modified, account, ypm_id FROM domain WHERE modified>?;"; private static final String SQL_LIST_DOMAIN_PREFIX_MODIFIED = "SELECT name, modified FROM domain " + "WHERE name>=? AND name?;"; private static final String SQL_LIST_DOMAIN_ROLE_NAME_MEMBER = "SELECT domain.name FROM domain " @@ -2728,7 +2728,9 @@ public DomainModifiedList listModifiedDomains(long modifiedSince) { while (rs.next()) { DomainModified dm = new DomainModified() .setName(rs.getString(ZMSConsts.DB_COLUMN_NAME)) - .setModified(rs.getTimestamp(ZMSConsts.DB_COLUMN_MODIFIED).getTime()); + .setModified(rs.getTimestamp(ZMSConsts.DB_COLUMN_MODIFIED).getTime()) + .setAccount(saveValue(rs.getString(ZMSConsts.DB_COLUMN_ACCOUNT))) + .setYpmId(rs.getInt(ZMSConsts.DB_COLUMN_PRODUCT_ID)); nameMods.add(dm); } } diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/utils/ZMSUtils.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/utils/ZMSUtils.java index 6844195e0f2..5a0ac614dec 100644 --- a/servers/zms/src/main/java/com/yahoo/athenz/zms/utils/ZMSUtils.java +++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/utils/ZMSUtils.java @@ -340,4 +340,12 @@ public static void threadSleep(long millis) { } catch (InterruptedException ignored) { } } + + public static boolean parseBoolean(final String value, boolean defaultValue) { + boolean boolVal = defaultValue; + if (value != null && !value.isEmpty()) { + boolVal = Boolean.parseBoolean(value.trim()); + } + return boolVal; + } } diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/ExceptionMapperTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/ExceptionMapperTest.java new file mode 100644 index 00000000000..d81f79b7f05 --- /dev/null +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/ExceptionMapperTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Oath, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yahoo.athenz.zms; + +import org.testng.annotations.Test; + +import javax.ws.rs.core.Response; + +import static org.testng.Assert.assertEquals; + +public class ExceptionMapperTest { + + @Test + public void testExceptionMappers() { + + JsonGeneralExceptionMapper mapper1 = new JsonGeneralExceptionMapper(); + Response response = mapper1.toResponse(null); + assertEquals(400, response.getStatus()); + + JsonMappingExceptionMapper mapper2 = new JsonMappingExceptionMapper(); + response = mapper2.toResponse(null); + assertEquals(400, response.getStatus()); + + JsonParseExceptionMapper mapper3 = new JsonParseExceptionMapper(); + response = mapper3.toResponse(null); + assertEquals(400, response.getStatus()); + + JsonProcessingExceptionMapper mapper4 = new JsonProcessingExceptionMapper(); + response = mapper4.toResponse(null); + assertEquals(400, response.getStatus()); + } +} diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/ZMSImplTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/ZMSImplTest.java index f4d43cebf21..0d4e9530cbd 100644 --- a/servers/zms/src/test/java/com/yahoo/athenz/zms/ZMSImplTest.java +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/ZMSImplTest.java @@ -48,6 +48,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.Response; import com.yahoo.athenz.auth.Authority; @@ -5317,7 +5318,7 @@ public void testGetSignedDomains() { "Test Domain2", "testOrg", adminUser); zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom2); - meta = createDomainMetaObject("Tenant Domain2", null, true, false, "12346", 0); + meta = createDomainMetaObject("Tenant Domain2", null, false, false, "12346", null); zms.putDomainMeta(mockDomRsrcCtx, "signeddom2", auditRef, meta); DomainList domList = zms.getDomainList(mockDomRsrcCtx, null, null, null, null, @@ -5333,9 +5334,8 @@ public void testGetSignedDomains() { "10.11.12.13", "GET", null); ResourceContext rsrcCtx = createResourceContext(sysPrincipal); - Response response = zms.getSignedDomains(rsrcCtx, null, null, null); - Object obj = response.getEntity(); - SignedDomains sdoms = (SignedDomains) obj; + Response response = zms.getSignedDomains(rsrcCtx, null, null, null, null); + SignedDomains sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); List list = sdoms.getDomains(); @@ -5360,13 +5360,12 @@ public void testGetSignedDomains() { } assertTrue(dom1Found); assertTrue(dom2Found); - + zms.privateKeyId = "1"; zms.privateKey = Crypto.loadPrivateKey(Crypto.ybase64DecodeString(privKeyK1)); - response = zms.getSignedDomains(rsrcCtx, null, null, null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, null, "all", null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5389,9 +5388,8 @@ public void testGetSignedDomains() { zms.privateKeyId = "2"; zms.privateKey = Crypto.loadPrivateKey(Crypto.ybase64DecodeString(privKeyK2)); - response = zms.getSignedDomains(rsrcCtx, null, null, null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, null, null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5407,9 +5405,8 @@ public void testGetSignedDomains() { // test metaonly=true // - response = zms.getSignedDomains(rsrcCtx, null, "tRuE", null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, "tRuE", null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5432,9 +5429,8 @@ public void testGetSignedDomains() { // test metaonly=garbage // - response = zms.getSignedDomains(rsrcCtx, null, "garbage", null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, "garbage", null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5454,9 +5450,8 @@ public void testGetSignedDomains() { // test metaonly=false // - response = zms.getSignedDomains(rsrcCtx, null, "fAlSe", null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, "fAlSe", null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5477,9 +5472,8 @@ public void testGetSignedDomains() { // test bad tag format // String eTag = "I am not good"; - response = zms.getSignedDomains(rsrcCtx, null, null, eTag); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, null, null, eTag); + sdoms = (SignedDomains) response.getEntity(); String eTag2 = response.getHeaderString("ETag"); assertNotNull(eTag2); assertNotEquals(eTag, eTag2); @@ -5492,9 +5486,8 @@ public void testGetSignedDomains() { Policy policy1 = createPolicyObject("SignedDom1", "Policy1"); zms.putPolicy(mockDomRsrcCtx, "SignedDom1", "Policy1", auditRef, policy1); - response = zms.getSignedDomains(rsrcCtx, null, null, eTag2); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(rsrcCtx, null, null, null, eTag2); + sdoms = (SignedDomains) response.getEntity(); eTag = response.getHeaderString("ETag"); assertNotNull(eTag); assertNotEquals(eTag, eTag2); @@ -5502,7 +5495,7 @@ public void testGetSignedDomains() { assertNotNull(list); assertEquals(1, list.size()); - response = zms.getSignedDomains(rsrcCtx, null, null, eTag); + response = zms.getSignedDomains(rsrcCtx, null, null, null, eTag); assertEquals(304, response.getStatus()); eTag2 = response.getHeaderString("ETag"); @@ -5528,9 +5521,8 @@ public void testGetSignedDomainsFiltered() { zms.privateKeyId = "0"; zms.privateKey = Crypto.loadPrivateKey(Crypto.ybase64DecodeString(privKey)); - Response response = zms.getSignedDomains(mockDomRsrcCtx, "signeddom1filtered", null, null); - Object obj = response.getEntity(); - SignedDomains sdoms = (SignedDomains) obj; + Response response = zms.getSignedDomains(mockDomRsrcCtx, "signeddom1filtered", null, null, null); + SignedDomains sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); List list = sdoms.getDomains(); @@ -5547,9 +5539,8 @@ public void testGetSignedDomainsFiltered() { // use domain=signeddom1filtered and metaonly=true // - response = zms.getSignedDomains(mockDomRsrcCtx, "signeddom1filtered", "true", null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(mockDomRsrcCtx, "signeddom1filtered", "true", null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5572,9 +5563,8 @@ public void testGetSignedDomainsFiltered() { // we're going to pass the domain name with caps and // make sure we still get back our domain - response = zms.getSignedDomains(mockDomRsrcCtx, "SignedDom1Filtered", null, null); - obj = response.getEntity(); - sdoms = (SignedDomains) obj; + response = zms.getSignedDomains(mockDomRsrcCtx, "SignedDom1Filtered", null, null, null); + sdoms = (SignedDomains) response.getEntity(); assertNotNull(sdoms); list = sdoms.getDomains(); @@ -5600,7 +5590,7 @@ public void testGetSignedDomainsNotSystemPrincipal() { "Test Domain1", "testOrg", adminUser); zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom1); - Response response = zms.getSignedDomains(mockDomRsrcCtx, null, null, null); + Response response = zms.getSignedDomains(mockDomRsrcCtx, null, null, null, null); assertEquals(response.getStatus(), ResourceException.BAD_REQUEST); zms.deleteTopLevelDomain(mockDomRsrcCtx, "SignedDom1", auditRef); @@ -14395,5 +14385,235 @@ public void testValidateServiceName() { System.clearProperty(ZMSConsts.ZMS_PROP_RESERVED_SERVICE_NAMES); System.clearProperty(ZMSConsts.ZMS_PROP_SERVICE_NAME_MIN_LENGTH); } + + @Test + public void testRetrieveSignedDomainMeta() { + + ZMSImpl zmsImpl = zmsInit(); + SignedDomain domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", 123, null); + assertNull(domain.getDomain().getAccount()); + assertNull(domain.getDomain().getYpmId()); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", 123, "unknown"); + assertNull(domain.getDomain().getAccount()); + assertNull(domain.getDomain().getYpmId()); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", 123, "account"); + assertEquals(domain.getDomain().getAccount(), "1234"); + assertNull(domain.getDomain().getYpmId()); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", 123, "ypmid"); + assertNull(domain.getDomain().getAccount()); + assertEquals(domain.getDomain().getYpmId().intValue(), 123); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", 123, "all"); + assertEquals(domain.getDomain().getAccount(), "1234"); + assertEquals(domain.getDomain().getYpmId().intValue(), 123); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, null, 123, "account"); + assertNull(domain); + + domain = zmsImpl.retrieveSignedDomainMeta("dom1", 1001, "1234", null, "ypmid"); + assertNull(domain); + } + + @Test + public void testRetrieveSignedDomainDataNotFound() { + + ZMSImpl zmsImpl = zmsInit(); + SignedDomain domain = zmsImpl.retrieveSignedDomainData("unknown", 1234); + assertNull(domain); + + // now signed domains with unknown domain name + + Authority principalAuthority = new com.yahoo.athenz.common.server.debug.DebugPrincipalAuthority(); + Principal sysPrincipal = principalAuthority.authenticate("v=U1;d=sys;n=zts;s=signature", + "10.11.12.13", "GET", null); + ResourceContext rsrcCtx = createResourceContext(sysPrincipal); + + Response response = zms.getSignedDomains(rsrcCtx, "unknown", null, null, null); + SignedDomains sdoms = (SignedDomains) response.getEntity(); + + assertNotNull(sdoms); + List list = sdoms.getDomains(); + assertEquals(0, list.size()); + } + + @Test + public void testGetSignedDomainsWithMetaAttrs() { + + // create multiple top level domains + TopLevelDomain dom1 = createTopLevelDomainObject("SignedDom1", + "Test Domain1", "testOrg", adminUser); + zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom1); + + // set the meta attributes for domain + + DomainMeta meta = createDomainMetaObject("Tenant Domain1", null, true, false, "12345", 0); + zms.putDomainMeta(mockDomRsrcCtx, "signeddom1", auditRef, meta); + + TopLevelDomain dom2 = createTopLevelDomainObject("SignedDom2", + "Test Domain2", "testOrg", adminUser); + zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom2); + + meta = createDomainMetaObject("Tenant Domain2", null, true, false, "12346", null); + zms.putDomainMeta(mockDomRsrcCtx, "signeddom2", auditRef, meta); + + DomainList domList = zms.getDomainList(mockDomRsrcCtx, null, null, null, null, + null, null, null, null, null); + List domNames = domList.getNames(); + int numDoms = domNames.size(); + + zms.privateKeyId = "0"; + zms.privateKey = Crypto.loadPrivateKey(Crypto.ybase64DecodeString(privKey)); + + Authority principalAuthority = new com.yahoo.athenz.common.server.debug.DebugPrincipalAuthority(); + Principal sysPrincipal = principalAuthority.authenticate("v=U1;d=sys;n=zts;s=signature", + "10.11.12.13", "GET", null); + ResourceContext rsrcCtx = createResourceContext(sysPrincipal); + + // we're going to ask for entries with ypm id so we'll only + // get one of the domains back - dom1 but not dom2 + + Response response = zms.getSignedDomains(rsrcCtx, null, "true", "ypmid", null); + SignedDomains sdoms = (SignedDomains) response.getEntity(); + assertNotNull(sdoms); + List list = sdoms.getDomains(); + assertNotNull(list); + + boolean dom1Found = false; + boolean dom2Found = false; + for (SignedDomain sDomain : list) { + DomainData domainData = sDomain.getDomain(); + if (domainData.getName().equals("signeddom1")) { + dom1Found = true; + } else if (domainData.getName().equals("signeddom2")) { + dom2Found = true; + } + } + assertTrue(dom1Found); + assertFalse(dom2Found); + + // now asking for specific domains with ypm id + // first signeddom1 with should return + + response = zms.getSignedDomains(rsrcCtx, "signeddom1", "true", "ypmid", null); + sdoms = (SignedDomains) response.getEntity(); + + assertNotNull(sdoms); + list = sdoms.getDomains(); + assertNotNull(list); + assertEquals(list.size(), 1); + + DomainData domainData = list.get(0).getDomain(); + assertEquals(domainData.getName(), "signeddom1"); + + // then signeddom2 with should not return + + response = zms.getSignedDomains(rsrcCtx, "signeddom2", "true", "ypmid", null); + sdoms = (SignedDomains) response.getEntity(); + + assertNotNull(sdoms); + list = sdoms.getDomains(); + assertNotNull(list); + assertEquals(list.size(), 0); + + zms.deleteTopLevelDomain(mockDomRsrcCtx, "SignedDom1", auditRef); + zms.deleteTopLevelDomain(mockDomRsrcCtx, "SignedDom2", auditRef); + } + + @Test + public void testGetSignedDomainsNotModified() { + + TopLevelDomain dom1 = createTopLevelDomainObject("SignedDom1", + "Test Domain1", "testOrg", adminUser); + zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom1); + + // set the meta attributes for domain + + DomainMeta meta = createDomainMetaObject("Tenant Domain1", null, true, false, "12345", 0); + zms.putDomainMeta(mockDomRsrcCtx, "signeddom1", auditRef, meta); + + zms.privateKeyId = "0"; + zms.privateKey = Crypto.loadPrivateKey(Crypto.ybase64DecodeString(privKey)); + + Authority principalAuthority = new com.yahoo.athenz.common.server.debug.DebugPrincipalAuthority(); + Principal sysPrincipal = principalAuthority.authenticate("v=U1;d=sys;n=zts;s=signature", + "10.11.12.13", "GET", null); + ResourceContext rsrcCtx = createResourceContext(sysPrincipal); + + EntityTag eTag = new EntityTag(Timestamp.fromCurrentTime().toString()); + Response response = zms.getSignedDomains(rsrcCtx, "signeddom1", null, null, eTag.toString()); + assertEquals(response.getStatus(), 304); + + zms.deleteTopLevelDomain(mockDomRsrcCtx, "SignedDom1", auditRef); + } + + @Test + public void testGetSignedDomainsException503() { + + ZMSImpl zmsImpl = zmsInit(); + + DBService dbService = Mockito.mock(DBService.class); + Mockito.when(dbService.getDomain("signeddom1", true)).thenThrow(new ResourceException(503)); + zmsImpl.dbService = dbService; + + Authority principalAuthority = new com.yahoo.athenz.common.server.debug.DebugPrincipalAuthority(); + Principal sysPrincipal = principalAuthority.authenticate("v=U1;d=sys;n=zts;s=signature", + "10.11.12.13", "GET", null); + ResourceContext rsrcCtx = createResourceContext(sysPrincipal); + + try { + zmsImpl.getSignedDomains(rsrcCtx, "signeddom1", null, null, null); + fail(); + } catch (ResourceException ex) { + assertEquals(ex.getCode(), 503); + } + } + + @Test + public void testGetSignedDomainsException404() { + + ZMSImpl zmsImpl = zmsInit(); + + DBService dbService = Mockito.mock(DBService.class); + Mockito.when(dbService.getDomain("signeddom1", true)).thenThrow(new ResourceException(404)); + zmsImpl.dbService = dbService; + + // now signed domains with unknown domain name + + Authority principalAuthority = new com.yahoo.athenz.common.server.debug.DebugPrincipalAuthority(); + Principal sysPrincipal = principalAuthority.authenticate("v=U1;d=sys;n=zts;s=signature", + "10.11.12.13", "GET", null); + ResourceContext rsrcCtx = createResourceContext(sysPrincipal); + + Response response = zmsImpl.getSignedDomains(rsrcCtx, "signeddom1", null, null, null); + SignedDomains sdoms = (SignedDomains) response.getEntity(); + + assertNotNull(sdoms); + List list = sdoms.getDomains(); + assertEquals(0, list.size()); + } + + @Test + public void testReceiveSignedDomainDataDisabled() { + + // create multiple top level domains + TopLevelDomain dom1 = createTopLevelDomainObject("SignedDom1Disabled", + "Test Domain1", "testOrg", adminUser); + zms.postTopLevelDomain(mockDomRsrcCtx, auditRef, dom1); + + // load the domain into cache and set the enabled to false + + zms.getAthenzDomain("signeddom1disabled", true); + zms.dbService.getAthenzDomainFromCache("signeddom1disabled", false).getDomain().setEnabled(false); + + // get the domain which would return from cache + + SignedDomain signedDomain = zms.retrieveSignedDomainData("signeddom1disabled", 0); + assertFalse(signedDomain.getDomain().getEnabled()); + + zms.deleteTopLevelDomain(mockDomRsrcCtx, "signeddom1disabled", auditRef); + } } diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/store/impl/JDBCCertRecordStoreFactoryTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/store/impl/JDBCCertRecordStoreFactoryTest.java new file mode 100644 index 00000000000..ffb11633c02 --- /dev/null +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/store/impl/JDBCCertRecordStoreFactoryTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 Oath Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.yahoo.athenz.zms.store.impl; + +import com.yahoo.athenz.auth.PrivateKeyStore; +import com.yahoo.athenz.zms.ZMSConsts; +import com.yahoo.athenz.zms.store.ObjectStore; +import org.mockito.Mockito; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; + +public class JDBCCertRecordStoreFactoryTest { + + @Test + public void testCreate() { + + System.setProperty(ZMSConsts.ZMS_PROP_JDBC_RW_STORE, "jdbc:mysql://localhost"); + System.setProperty(ZMSConsts.ZMS_PROP_JDBC_RW_USER, "user"); + System.setProperty(ZMSConsts.ZMS_PROP_JDBC_RW_PASSWORD, "password"); + + PrivateKeyStore keyStore = Mockito.mock(PrivateKeyStore.class); + Mockito.doReturn("password").when(keyStore).getApplicationSecret("jdbc", "password"); + + JDBCObjectStoreFactory factory = new JDBCObjectStoreFactory(); + ObjectStore store = factory.create(keyStore); + assertNotNull(store); + } +} diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnectionTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnectionTest.java index 96d06d30630..38d859071a0 100644 --- a/servers/zms/src/test/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnectionTest.java +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/store/jdbc/JDBCConnectionTest.java @@ -4676,6 +4676,10 @@ public void testListModifiedDomains() throws Exception { .thenReturn(true).thenReturn(true).thenReturn(false); Mockito.when(mockResultSet.getString(ZMSConsts.DB_COLUMN_NAME)) .thenReturn("domain1").thenReturn("domain2").thenReturn("domain3"); // 3 domains + Mockito.when(mockResultSet.getString(ZMSConsts.DB_COLUMN_ACCOUNT)) + .thenReturn("acct1").thenReturn("acct2").thenReturn("acct3"); // 3 domains + Mockito.when(mockResultSet.getString(ZMSConsts.DB_COLUMN_PRODUCT_ID)) + .thenReturn("1234").thenReturn("1235").thenReturn("1236"); // 3 domains Mockito.doReturn(new java.sql.Timestamp(1454358916)).when(mockResultSet).getTimestamp(ZMSConsts.DB_COLUMN_MODIFIED); DomainModifiedList list = jdbcConn.listModifiedDomains(1454358900); diff --git a/servers/zms/src/test/java/com/yahoo/athenz/zms/utils/ZMSUtilsTest.java b/servers/zms/src/test/java/com/yahoo/athenz/zms/utils/ZMSUtilsTest.java index 94eb8ab03a6..1df71801199 100644 --- a/servers/zms/src/test/java/com/yahoo/athenz/zms/utils/ZMSUtilsTest.java +++ b/servers/zms/src/test/java/com/yahoo/athenz/zms/utils/ZMSUtilsTest.java @@ -250,4 +250,15 @@ public void testRemoveMembersInvalidInput() { assertEquals(list.size(), 1); assertEquals(list.get(0).getMemberName(), "member1"); } + + @Test + public void testParseBoolean() { + assertEquals(true, ZMSUtils.parseBoolean(null, true)); + assertEquals(false, ZMSUtils.parseBoolean(null, false)); + assertEquals(true, ZMSUtils.parseBoolean("", true)); + assertEquals(false, ZMSUtils.parseBoolean("", false)); + assertEquals(true, ZMSUtils.parseBoolean("true", false)); + assertEquals(false, ZMSUtils.parseBoolean("false", true)); + assertEquals(false, ZMSUtils.parseBoolean("unknown", false)); + } }