I've been configurating a LDAP server on a linux instance using AWS EC2.
Up to now, I successfully set up LDAP and phpLDAPadmin to work together.
I've created Users and Groups "Organisation Units". I've added users and groups to those "OU"s.
Now I want to grand access to specific parts of my LDAP tree to the "Users" members of a "Group". That's what I wasn't able to configure up to now...
My LDAP tree looks like this:
+--> dc=www,dc=website,dc=com (3)
---> cn=admin
+--> ou=groups (4)
| ---> cn=admin_users
| ---> cn=app1_users
| ---> cn=app2_users
| ---> cn=basic_users
+--> ou=users (3)
| ---> cn=user1
| ---> cn=user2
| ---> cn=user3
Let's say that I added user1 + user2 to the "memberUid" list of "app1_users" and user2 + user3 to the "memberUid" list of "app2_users".
I want:
cn=admin have full rights/access to the tree
app1_users can connect (to phpLDAPadmin) and add new members to the the group itself
the same for app2_users' users
A connected user (on phpLDAPadmin) should only see the tree (and child substrees) he's part of.
Here are the ACI I tried (but whose were obsiouvly not working):
access to attrs=shadowLastChange
by self write
by dn="cn=admin,dc=www,dc=website,dc=com" write
by * read
access to attrs=userPassword
by self write
by dn="cn=admin,dc=www,dc=website,dc=com" write
by anonymous auth by * none
access to dn.base=""
by * read
access to dn.subtree="cn=app1_users,ou=groups,dc=www,dc=website,dc=com"
by group.base="cn=app1_users,dc=www,dc=website,dc=com" write
by dn.base="cn=admin,dc=www,dc=website,dc=com" write
by * none
access to dn.subtree="cn=app2_users,ou=groups,dc=www,dc=website,dc=com"
by group.base="cn=app2_users,dc=www,dc=website,dc=com" write
by dn.base="cn=admin,dc=www,dc=website,dc=com" write
by * none
access to *
by self write
by dn="cn=admin,dc=www,dc=website,dc=com" write
by * read
Is there something wrong with my configuration ?
If cn=admin,... is your rootDn, it has all the rights there are and shouldn't be addressed in your own access rules.
For group management try:
access to dn.base="cn=app1_users,ou=groups,dc=www,dc=website,dc=com"
by group.exact="cn=app1_users,dc=www,dc=website,dc=com" write
There's an implicit last rule access to * by * none, so no need for by * none in your own rules.
Generally, add your rules one by one to the list - it's easier to watch the effects that way.
Related
I have a secret key-value pair in Secrets Manager in Account-1 in us-east-1. This secret is encrypted using a Customer managed KMS key - let's call it KMS-Account-1. All this has been created via console.
Now we turn to CDK. We have cdk.pipelines.CodePipeline which deploys Lambda to multiple stages/environments - so 1st to { Account-2, us-east-1 } then to { Account-3, eu-west-1 } and so on. This has been done.
The lambda code in all stages/environments above, now needs to be changed to use the secret key-value pair present with Account-1's us-east-1 SecretsManager by getting it via secretsmanager client. That code should probably look like this (python):
client = boto3.session.Session().client(
service_name = 'secretsmanager',
region_name = 'us-east-1'
)
resp = client.get_secret_value(
SecretId='arn:aws:secretsmanager:us-east-1:<ACCOUNT-1>:secret:name/of/the/secret'
)
secret = json.loads(resp['SecretString'])
All lambdas in various accounts and regions (ie. environments) will have the exact same code as above since the secret needs to be fetched from Account-1 in us-east-1.
Firstly I hope this is conceptually possible. Is that right?
Next how do I change the cdk code to facilitate this? How will the code-deploy in code-pipeline get permission to import this custom kms key and SecretManager' secretand apply correct permissions for cross account access by the lambdas that the cdk pipeline creates ?
Can someone please give some pointers?
This is bit tricky as CloudFormation, and hence CDK, doesn't allow cross account/cross stage references because CloudFormation export doesn't work cross account as far as my understanding goes. All these patterns of "centralised" resources fall into that category - ie. resource in one account (or a stage in CDK) referenced by other stages.
If the resource is created outside the context of CDK (like via console), then you might as well hardcode the names/arns/etc. throughout the CDK code where its used and that should be sufficient.
For resources that have the ability to hold resource based policies, it's simpler as you can just attach the cross-account access permissions to them directly - again, offline via console since you are maintaining it manually anyway. Each time you add a stage (account) to your pipeline, you will need to go to the resource and add cross-account permissions manually.
For resources that don't have resource based policies, like SSM for eg., things are a bit roundabout as you will need to create a Role that can be assumed cross-account and then access the resource. In that case you will have to separately maintain the IAM Role too and manually update the trust policy to other accounts as you add stages to your CDK pipeline. Then, as usual hardcode the role arn in your CDK code, assume it in some CustomResource lambda and use it.
It gets more interesting if the creation is also done in the CDK code itself (ie. managed by CloudFormation - not done separately via console/aws-cli etc.). In this case, many times you wouldn't "know" the exact ARNs as the physical-id would be generated by CloudFormation and likely be a part of the ARN. Even influencing the physical-id yourself (like by hardcoding the bucket name) might not solve it in all cases. Eg. KMS ARNs and SecretManager ARNs append unique-ids or some sort of hashes to the end of the ARN.
Instead of trying to work all that out, it would be best left untouched and let CFn generate whatever random name/arn it chooses. To then reference these constructs/ARNs, just put them into SSM Parameters in the source/central account. SSM doesn't have resource based policy that I know of. So additionally create a role in cdk that trusts the accounts in your cdk code. Once done, there is no more maintenance - each time you add new environments/accounts to CDK (assuming its a cdk pipeline here), the "loop" construct that you will create will automatically add the new account into the trust relationship.
Now all you need to do is to distribute this role-arn and the SSM Parameternames to other stages. Choose an explicit role-name and SSM Parameters. The manual ARN construction given a rolename is pretty straightforward. So distribute that and SSM Parameters around your CDK code to other stages (compile time strings instead of references). In target stages, create custom-resource(s) (AWSCustomResource) backed by AwsSdkCall lambda to simply assume this role-arn and make the SDK call to retrieve the SSM Parameter values. These values can be anything, like your KMS ARNs, SecretManager's full ARNs etc. which you couldn't easily guess. Now simply use these.
Roundabout way to do a simple thing, but so far that is all I could do to get this to work.
#You need to maintain this list no matter what you do - so it's nothing extra
all_other_accounts = [ <list of accounts that this cdk deploys to> ]
account_principals = [iam.AccountPrincipal(a) for a in all_other_account]
role = iam.Role(
assumed_by = iam.CompositePrincipal(*account_principals), #auto-updated as you change the list above
role_name = some_explicit_name,
...
)
role_arn = f'arn:aws:iam::<account-of-this-stack>:role/{some_explicit_name}'
kms0 = kms.Key(...)
kms0.grant_decrypt(role)
# Because KMS also needs explicit resource policy even if role policy allows access to it
kms0.add_to_role_policy(iam.PolicyStatement(principals = [iam.ArnPrincipal(role_arn)], actions = ...))
kms1 = kms.Key(...)
kms1.grant_decrypt(role)
kms0.add_to_role_policy(... same as above ...)
secrets0 = secretsmanager.Secret(...) #maybe this is based off kms0
secrets0.grant_read(role)
secrets1 = secretsmanager.Secret(...) #maybe this is based off kms1
secrets1.grant_read(role)
# You can turn all this into a loop ofc.
ssm0 = ssm.StingParameter(self, '...', parameter_name = 'kms0_arn', string_value = kms0.key_arn, ...)
ssm0.grant_read(role)
ssm1 = ssm.StingParameter(self, '...', parameter_name = 'kms1_arn', string_value = kms1.key_arn, ...)
ssm1.grant_read(role)
ssm2 = ssm.StingParameter(self, '...', parameter_name = 'secrets0_arn', string_value = secrets0.secret_full_arn, ...)
ssm2.grant_read(role)
...
#Now simply pass around the role and ssm parameter names
for env in environments:
MyApplicationStage(self, <...>, ..., role_arn = role_arn, params = [ 'kms0_arn', 'kms1_arn', ... ], ...)
And then in the target stage(s):
for parm in params:
fn = AwsSdkCall('ssm', 'get_parameter', { "Name": param }, ...)
acr = AwsCustomResource(..., on_create = fn, on_update = fn, ...)
collect['param'] = acr.get_response_field('Parameter.Value')
Now do whatever you want with the collected artifacts, including supplying them as environment variables to your main service lambda (which will be resolved at deploy time).
Remember they will all be Tokens and resolved only at deploy time, but that's true of any resource, whether or not via custom-resource and it shouldn't matter.
That's a generic pattern which should work for any case.
(GitHub link where this question was asked and I had answered it there too)
I'm attempting to rewrite an application that was originally developed with Spring. The user authentication is provided via Spring Security that uses Bcrypt to generate and check hashed passwords.
They are stored in the database in the format shown below. As far as I can tell, this is how it is represented:
| |RR| Salt | Hashed Password |
$2a$10$Dh23I3CO6l1n3mOofdazreNLg2OHxzDrxyGGZEstTbITKs.cX3N/u
(Where RR is the number of rounds)
I've tried migrating this to a new table structure as show in "Table 3. Example Table" under Using a Hashed Password Representation of 4.6. Component Documentation, for example:
NAME | PASSWORD | SALT |ITERATION_COUNT|
=====|=================================|========================|===============|
test | NLg2OHxzDrxyGGZEstTbITKs.cX3N/u | Dh23I3CO6l1n3mOofdazre | 10 |
I have configured the mapper in application.properties as below:
quarkus.security.jdbc.principal-query.sql=SELECT u.password, u.salt, u.iteration_count FROM test_user u WHERE u.name=?
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.enabled=true
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.password-index=1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.hash-encoding=base64
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.salt-index=2
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.salt-encoding=base64
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.iteration-count-index=3
However, I either get an error caused by invalid base64 characters (which isn't a total surprise as the implementation in Spring Security states it's not a MIME compatible base64 implementation) or, when that error is not present, it fails to verify the password.
How would I be able to migrate all the users to the Bcrypt implementation that Quarkus uses?
So I didn't need to split up the salt, hash and iteration count at all. You can continue to use the current 'single string' format. The trick is to configure the mapper as follows (note the -1 for the salt and iteration-count properties):
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.enabled=true
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.password-index=1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.salt-index=-1
quarkus.security.jdbc.principal-query.bcrypt-password-mapper.iteration-count-index=-1
Although I don't see it mentioned in the Wildfly Elytron docs, or in the Quarkus configuration documentation, it is clearly handled (see PasswordKeyMapper.java on GitHub)
The logic caters for when these two properties are set to -1. It then parses the full string and verifies the password successfully.
I'm trying to get a list of Audit Logs similar to what is displayed in Google console page (IAM/Audit Logs) using the Golang API GetIamPolicy as described here:
https://cloud.google.com/resource-manager/reference/rest/v1/projects/getIamPolicy
If one service has at least one of its Log Types set (Data Read, Data Write or Admin Read), GetIamPolicy will return it, but if it does not have any set then the service is omitted from the response.
As an example, if my project has three services A, B and C and A has Data Read enabled, B has Admin Read enabled and C doesn't have anything enabled, GetIamPolicy will only return A and B.
GetIamPolicyRequest struct seems to have fields designed for this scenario (NullFields and ForceSendFields), but I couldn't make it work. Example:
rb := &cloudresourcemanager.GetIamPolicyRequest{}
rb.ForceSendFields = []string{"LogType"}
rb.NullFields = []string{"LogType"}
policyOptions := &cloudresourcemanager.GetPolicyOptions{}
policyOptions.ForceSendFields = []string{"LogType"}
policyOptions.NullFields = []string{"LogType"}
policyOptions.RequestedPolicyVersion = 3
rb.Options = policyOptions
Any ideas on how to retrieve the missing services?
Background
I working on (modifying) a vbscript intended to create an AD shadow group formed by all users of several OU's.
The script logs into a remote AD, using alternate credentials.Note: The user I log in as, have full AD read access, but only inherited write access to the OU containing the group I'm adding members to.
Problematic code
The script is easily able to log in, scan for users on the OU's, open the shadow group and list it's current members, perform compares and locate the users to add and remove....but...
the actual adding (and removing) of members to the named security group fails, Error: 80070005 Srce: Active Directory Desc: Access is denied., when I apply .SetInfo.
I'm using this code to read and write:
aMembers = oGroup.GetEx("member") ' This gets populated as it should.
oGroup.PutEx ADS_PROPERTY_APPEND, "member", Array("CN=Doe\, John [LOCATION/COUNTRY],OU=foo,OU=bar,OU=Country,DC=domain,DC=org")
oGroup.SetInfo ' This fails
Just in case this is related to how I log into the AD, here's the code:
' Open an ADO connection using full credentials
Set oConnection = CreateObject("ADODB.Connection")
oConnection.Provider = "ADsDSOObject"
oConnection.Properties("User ID") = sLDAP_USER ' "domain\user"
oConnection.Properties("Password") = sLDAP_PASS ' "pass!word"
oConnection.Properties("Encrypt Password") = True
oConnection.Properties("ADSI Flag") = ADS_SECURE_AUTHENTICATION Or ADS_SERVER_BIND
oConnection.Open "Active Directory Provider"
Verifying my login users rights
I've seen lots of similar posts with this sort of error, and have only seen answers stating that this is a permission problem - however never seen a description of what permission was missing/wrong. The Access is denied error really made me doubt that the login I used had the right permissions, so I attempted to add members to the group by using JXplore. It works, but only if I enable the option to ignore schema checking (Based on online advice, when using JXplore with AD instead of pure LDAP).
Edit: Without ignoring the schema checking, the following properties are also requested to be populated: instanceType, nTSecurityDescriptor and objectCatagory, but I notice they are blank on existing users.
Questions
Did I fall into an obvious pitfall?
Do I also somehow need to ignore the schema in my script? If so, how to do that?
I am configuring net-snmp.
Below is my snmpd.conf:
#com2sec NAME SOURCE COMMUNITY
com2sec sec_localuser_localhost 127.0.0.1 localuser
com2sec sec_testuser_tests.sse.hin.hellomi.com 127.0.0.1 testuser
#group NAME MODEL SECURITY
group grp1 v2c sec_localuser_localhost
group testgroup v2c sec_testuser_tests.sse.hin.hellomi.com
#view NAME TYPE SUBTREE [MASK]
view all included .iso
view iso included .all
#access NAME CONTEXT MODEL LEVEL PREFX READ WRITE NOTIFY
access grp1 "" any noauth exact all - all
access testgroup "" any noauth exact all all all
in the log of messages, I could find the following error:
snmpd.conf: line 6: Error: security name too long
So it means the hostname: tests.sse.hin.hellomi.com is too long
My question is: What is the maximum length for the security name? I tried from google, but I found nothing about the maximum length.
Anyway, I know I can test to find the maximum length, but I just wonder if there is any formal limit on the maximum length.
Thanks!
SECNAME is an internal security identifier it identify a SNMP communauty (you are using localuser it's generaly public or private) comming from a computer (127.0.0.1) so why do you want to map it to a computername.
If you absolutly want to know the limit length, Net-SNMP is open source, so you can grep the error message into the sources.
The limit is the same as an SnmpAdmingString, 32 characters.