Iterating through over a map of lists in terraform - foreach

I'm trying to attach list of policies to roles and I have defined my variable as follows:
variable "role_map_user_policies" {
type = map(list(string))
default = {
role1 = ["policy_arn1", "policy_arn2"]
role2 = ["policy_arn1", "policy_arn2", "policy_arn3"]
}
my resource block as follows
locals {
policy_attachments = flatten([for roleName, policies in var.role_map_user_policies :
[for policy_arn in policies: {
roleName = roleName
policy_arn = policy_arn
}
]
])
}
resource "aws_iam_role_policy_attachment" "customer_managed_policy_attachment" {
for_each = {
for entry in local.policy_attachments: "${entry.roleName}.${entry.policy_arn}" => entry
}
role = each.value.roleName
policy_arn = each.value.policy_arn
Here it shows errors like "unresolved reference" over entry.roleName and entry.policy_arn each.value.roleName each.value.policy_arn
I'm not able to get it where it is going wrong. Any help would be appreciated. Thank you
expecting it should assign the role name and list of policies to the arugments

Related

ASP.net core MVC multitenant configuration

I'm building a multitenant web application in ASP.net core MVC and I need to create multitenant support for configuration in appsettings.json.
I want my settings to look like this:
{
'Section1': {
'Key1': 'Value1',
'Key2': 'Value2',
}
'Tenants': {
'TenantA': {
'Section1': {
'Key1': 'Value 1 for Tenant A'
}
},
'TenantB': {
'Section1': {
'Key2': 'Value 2 for Tenant B'
}
}
}
}
In other words, the structure of the configuration should be duplicated in Tenants section and this configuration should override the default one.
When I resolve Section1 options using Options pattern (https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-7.0) I want to get these values:
For TenantA: Key1 = Value 1 for Tenant A; Key2 = Value 2
For TenantB: Key1 = Value 1; Key2 = Value 2 for Tenant B
I have my custom ITenantProvider interface which is Scoped service and it provides name of current tenant. It means that every http request can serve different tenant and so the options should be also different every http request.
I've tried to override IOptionsFactory (https://github.com/dotnet/runtime/blob/4aa4d28f951babd9b26c2e4cff99a3203c56aee8/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs) and do some magic there.
public TOptions Create(string name) {
var tenantProvider = _httpContextAccessor?.HttpContext?.RequestServices.GetService<ITenantProvider>();
// I have my current tenant key, but what to do now?
var tenantKey = tenantProvider?.GetTenant()?.Key;
TOptions options = CreateInstance(name);
foreach (IConfigureOptions<TOptions> setup in _setups) {
if (setup is IConfigureNamedOptions<TOptions> namedSetup) {
namedSetup.Configure(name, options);
} else if (name == Options.DefaultName) {
setup.Configure(options);
}
}
foreach (IPostConfigureOptions<TOptions> post in _postConfigures) {
post.PostConfigure(name, options);
}
if (_validations.Length > 0) {
var failures = new List<string>();
foreach (IValidateOptions<TOptions> validate in _validations) {
ValidateOptionsResult result = validate.Validate(name, options);
if (result is not null && result.Failed) {
failures.AddRange(result.Failures);
}
}
if (failures.Count > 0) {
throw new OptionsValidationException(name, typeof(TOptions), failures);
}
}
return options;
}
Actually, I've tried to use this tutorial https://michael-mckenna.com/multi-tenant-asp-dot-net-core-application-tenant-specific-configuration-options but this can only override the configuration using some callback Program.cs which isn't exactly what I need.
Does somebody have any idea how to implement this?

Using Mock.Setup on two different methods doesn't match on one and instead returns null

I am new in Unit Testing. I am using Moq for unit testing. I have a situation where I have to mock for two different method in same section :
I have an Action Method like below :
public ActionResult Login(someparameters)
{
//code...
var user = userRepository.SelectAllUserByEmail(someparamters); //first method
//....
var userDetails = userRepository.ValidateUser(someparameters);//second method
}
here is my unit testing part :
userrepositoryMock.Setup(r => r.SelectAllUserByEmail(someparameters))
.Returns(new List<User>() { new User { Salt = strSalt, FundraiserAdminId = fundadmind, StatusCode = statusCode, UserTypeId = userTypeId, HomePageURL = homepageURL, OrganizationId = organizationId } } );
userrepositoryMock.Setup(k => k.ValidateUser(someparamters))
.Returns(new User { Salt = strSalt, FundraiserAdminId = fundadmind, StatusCode = statusCode, UserTypeId = userTypeId, HomePageURL = homepageURL, OrganizationId = organizationId });
but this only mocks SelectAllUserByEmail method for ValidateUser it returns null.
You haven't specified what type (or types) someparameters represent, but I'll bet that at least one of them is a reference type (other than a simple string).
For reference types (like object instances), using Moq's .Setup on an exact instance is usually a bad idea, as this will require that the exact same reference is passed to the mocked class in order for the Setup to match and return the provided output.
Here's a simple MVCE which reproduces the problem. Given the following code:
public class User
{
public string Name { get; set; }
}
public interface IMyInterface
{
string GetUserName(User user);
}
The following Unit Test demonstrates that a Setup bound to a specific object instance (aUser) will NOT match if another reference (sameUser) is passed to the Mock:
[Test]
public void TestGetUserBad()
{
var mock = new Mock<IMyInterface>();
var aUser = new User { Name = "User1" };
var sameUser = new User { Name = "User1" };
mock.Setup(x => x.GetUserName(aUser)).Returns<User>(u => u.Name);
Assert.AreEqual("User1", mock.Object.GetUserName(aUser),
"The mock has been setup for aUser, so this works");
Assert.AreEqual(null, mock.Object.GetUserName(sameUser),
"aUser is a different reference than sameUser hence fails");
}
Instead, you should use Moq's It.Is<> (with a predicate) or It.IsAny<> (any) matchers to allow the match for any reference meeting the predicate (if any).
[Test]
public void TestGetUserGood()
{
var mock = new Mock<IMyInterface>();
var aUser = new User { Name = "User1" };
var sameUser = new User { Name = "User1" };
mock.Setup(x => x.GetUserName(It.IsAny<User>())).Returns<User>(u => u.Name);
Assert.AreEqual("User1", mock.Object.GetUserName(aUser),
"The mock has been setup for any user, so this works");
Assert.AreEqual("User1", mock.Object.GetUserName(sameUser),
"The mock has been setup for any user, so this works");
}
Edit
Out of interest, if you suspect one of your Mock setups isn't being matched as intended (as Moq will return default(T) when using loose mocking if no match is found), you can temporarily switch MockBehaviour to Strict, which will throw if a Setup isn't matched.
e.g. applying the below to TestGetUserBad
var mock = new Mock<IMyInterface>(MockBehavior.Strict);
Results in:
Moq.MockException : IMyInterface.GetUserName(User) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.
I have solved this issue by adding following code :
userrepositoryMock.SetReturnsDefault(new User { Salt = strSalt, FundraiserAdminId = fundadmind, StatusCode = statusCode, UserTypeId = userTypeId, HomePageURL = homepageURL, OrganizationId = organizationId });

mvc entity framework many to many user and role insert

I have an mvc project with database first entityframework. In Project I have 3 tables.
Users >>> UsersInRoles <<< Roles with many to many relationship.
and my CreateUser codes below;
public bool CreateUser(string email, string password, string birthday,string firstname,string lastname)
{
bool result;
var dogumgunu = Convert.ToDateTime(birthday);
var sifre = FormsAuthentication.HashPasswordForStoringInConfigFile(password, "sha1");
var confirmation = CreateConfirmationToken(email);
try
{
var user = new User
{
UserName = email,
Password = sifre,
UserJoinDate = DateTime.Now,
UserBirthDay = dogumgunu,
UserConfirmationToken = confirmation,
UserID = Guid.NewGuid(),
MemberFirstName = firstname,
MemberLastName = lastname
};
var role = new Role
{
RoleName = "Client"
};
user.Roles.Add(role); //problem is here!!!!!!!!!
_bb.Users.AddObject(user);
_bb.SaveChanges();
result = true;
}
catch (Exception)
{
result = false;
}
return result;
}
In this code I am new user creating. And I am adding a role. But This code include a new Role in Roles table. I dont want to this. I want to just add UsersInRoles table a new user. What is wrong? Thanks for reply.
Swap these two lines:
_bb.Users.AddObject(user);
user.Roles.Add(role);
because AddObject converts the whole object graph to the Added state. If you add the role afterwards, its state will remain Unchanged.
And you should fetch the role from the database first or create a Role object that only has an existing RoleId. (A so called stub entity).
So in stead of new Role you could do
var role = _bb.Roles.Single(r => r.RoleName == "Client");

using GroupPrincipal can you get additional info from UserPrincipal

I am looking up users who are members of an AD group using GroupPrincipal.
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, "Advisors");
I need to get the EmployeeID field from this lookup but I believe this is only possible using UserPrincipal.
var members = group.Members.Select(x => new DomainContext() { EmployeeID = x.EmployeeId, FullName = x.DisplayName }).ToList();
Does anyone know of a way round this?
You have to use UserPrincipal unless you're using the underlying DirectoryEntry/DirectorySearcher classes.
You should use .GetMembers() instead of .Members then you can do stuff like:
var userMembers = group.GetMembers().OfType<UserPrincipal>();
foreach( var member in userMembers) {
string empid = member.EmployeeId; //do something with the EmployeeId
}

MVC4: Getting Active Directory User Guid

Once a user is logged into a Windows-Authentication site, how do I get their Active Directoy user guid from the User.
Eg in an Action:
ViewBag.Message = User.Identity.GUID????
You should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find the current user
UserPrincipal user = UserPrincipal.Current;
if(user != null)
{
// get guid
var userGuid = user.Guid;
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
string userName = user.Identity.Name.Split('\\')[1];
using (var oRoot = new DirectoryEntry(ConfigurationManager.AppSettings["LDAPDomain"], null, null, AuthenticationTypes.Secure))
{
using (var deSearch = new DirectorySearcher(oRoot))
{
deSearch.Filter = string.Format("(&(sAMAccountName={0}))", userName);
SearchResult searchResult = deSearch.FindOne();
if (searchResult != null)
{
DirectoryEntry de = searchResult.GetDirectoryEntry();
}
}
}

Resources