jeudi 1 avril 2021

What design pattern fits managing Active Directory Security Groups via the ldap3 library with python?

Issue

I wrote a script a while back that creates AD security groups. It triggers automatically whenever we create a new service, it creates AD groups based on a template. This works great, however I quickly realized a new iteration is required which can delete and update the groups based on the changes made in the template.

I can add additional methods and make some slight changes to address this, but since the codebase is currently still minuscule I figured this would be a good opportunity to start practicing patterns if possible. What approach/pattern should I use when refactoring and why?

Current Code

#!/usr/bin/env python3
"""Creates the Active Directory groups required by the ***** that authenticate via *****.

Attributes;
    KWARGS (dict): Keyword arguments utilized with the ldap3.Connection
        class.
    LOGGER (logging.Logger): A logging channel.
    SERVER (ldap3.Server): Object representation of the LDAP server.
    SGS (list): A list of groups to be created.
"""
import logging
import os
from sys import stdout

import boto3
import yaml
from ldap3 import Connection, NTLM, Server
from ldap3.extend.microsoft.addMembersToGroups import ad_add_members_to_groups
from ldap3.core.exceptions import LDAPEntryAlreadyExistsResult, LDAPNoSuchObjectResult

logging.basicConfig(stream=stdout)

LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)

SERVER = Server(os.environ['LDAP_SERVER'], use_ssl=True)

with open('templates/security_groups.yaml') as fil:
    SGS = yaml.load(fil, Loader=yaml.FullLoader)

def create_security_group(name: str = '', desc: str = '',
                          membership: list = None,
                          domain_local: bool = False) -> None:
    """Creates an active directory group.

    Args:
        name: The name of the active directory group.
        desc: The description of the group.
        membership: The groups to add the group to.
        domain_local: Creates a domain local security group if True,
            otherwise a global security group is generated.
    """
    attribs = {
        'cn': name,
        'description': desc,
        'groupType': '-2147483646', # Global Security Group
        'sAMAccountName': name,
    }
    if domain_local:
        attribs['groupType'] = '-2147483644' # Domain local group
    with Connection(SERVER, **KWARGS) as conn:
        LOGGER.info('Creating %s.', name)
        try:
            conn.add(
                get_distinguished_name(name, ou_='OU WHERE SIMILAR GROUPS ARE STORED AND MANAGED'),
                object_class='Group',
                attributes=attribs
            )
        except LDAPEntryAlreadyExistsResult:
            LOGGER.info('%s already exists.', name)
        if membership:
            LOGGER.info('Adding %s to the following groups: %s', name, membership)
            try:
                ad_add_members_to_groups(
                    conn,
                    [get_distinguished_name(member, ou_='MOCK') for member in membership],
                    [get_distinguished_name(name, ou_='OU WHERE SIMILAR GROUPS ARE STORED AND MANAGED')],
                )
            except LDAPNoSuchObjectResult:
                LOGGER.info('Please check if the following groups exists in MOCK:\n\n%s',
                            membership)

def get_connection_args() -> dict:
    """Returns the ldap connection arguments.

    Returns:
        The ldap connection arguments.
    """
    kwargs = {
        'authentication': NTLM,
        'raise_exceptions': True,
    }
    return kwargs

def get_distinguished_name(name: str, ou_: str = '') -> str:
    """Returns the AD distinguished name.

    Args:
        name: The AD common name.
        ou_: The organizational unit to add to the search base.
            Ex: 'MOCK'

    Returns:
        The distinguished name.
    """
    return f'cn={name},'+get_ldap_base(ou_=ou_)

def get_ldap_base(ou_: str = '') -> str:
    """Returns the LDAP search base.

    Args:
        ou_: The organizational unit to add to the search base.
            Ex: 'MOCK'

    Returns:
        The LDAP search base.
    """

    dc_ = 'dc=example,dc=com'
    ous = ou_.split('/')
    ous.reverse()
    _ous = []
    for _ou in ous:
        _ous.append(f'ou={_ou}')
    return ','.join(_ous)+f',{dc_}'

def get_lob_security_groups(team: str = '', owners: str = '', tier: str = '') -> list:
    """Gets the teams associated with the
    account.

    Args:
        team: The initials of the team.
        owners: The IDs associated with the primary and secondary owner of the
            AD group.
        tier: The tier of the service. Ex: sandbox

    Returns
        The AD groups to create.
    """
    owners_ = []
    for owner in owners.upper().split():
        owners_.append(f'{owner} '+get_name_from_id(owner))

    sgs = []
    for role in ['developer', 'readonly', 'sandbox_developer']:
        if tier.lower() != 'development' and role == 'developer':
            continue
        if tier.lower() != 'sandbox' and role == 'sandbox_developer':
            continue
        desc = f'Grants the {team.upper()} {role} access to the service.'
        if role == 'developer':
            desc = f'****: {desc}'
        else:
            desc = ', '.join(owners_)+f': {desc}.'
        sgs.append({
            'name': '{service}-'+team.lower()+'-{shortname}-'+role,
            'desc': desc,
            'membership': [],
        })
    return sgs

def get_name_from_id(id_: str) -> str:
    """Translates the Active Directory user ID to a first and last name.

    Args:
        id_: The Active Directory user ID.

    Returns:
        The first and last name of the user.
    """
    with Connection(SERVER, **KWARGS) as conn:

        base = get_ldap_base(ou_='MOCK')
        filt = f'(&(objectclass=person)(cn={id_.upper()}))'
        conn.search(base, filt, attributes=['givenName', 'sn'])
        for entry in conn.entries:
            return f'{entry["givenName"]} {entry["sn"]}'
    return ''

def main() -> None:
    """Creates the Active Directory groups required by the *****
    that authenticate via *****.
    """
    SGS.extend(get_lob_security_groups(
        team=os.environ['TEAM'],
        owners=os.environ['OWNERS'],
        tier=os.environ['TIER'])
    )
    for sg_ in SGS:
        if os.environ['TIER'].lower() != 'development' \
            and sg_['name'].endswith('****'):
            continue
        if any(['developer' in sg_['name'], 'readonly' in sg_['name']]):
            create_security_group(
                name=sg_['name'].format(service=os.environ['SERVICE'],
                                        shortname=os.environ['SHORTNAME']),
                desc=sg_['desc'],
                membership=sg_['membership'],
                domain_local=True
            )
        else:
            create_security_group(
                name=sg_['name'].format(service=os.environ['SERVICE'],
                                        shortname=os.environ['SHORTNAME']),
                desc=sg_['desc'],
                membership=sg_['membership']
            )

if __name__ == '__main__':
    KWARGS = get_connection_args()
    main()

which design pattern allows me to implement two different classes, each class has a list of objects of the other class?

I have a class A and class B, class A has a list of instances of class B and class B has a list of instances of class A, in sql language, this is many to many relationship, is there a design pattern that helps in the implementation of these classes or am I overthinking it and it is just as simple as just assigning a respective list for each class?

Thanks

Is there a good C# pattern for composition with interfaces?

Suppose that I have a base interface, IBase, that describes some minimal behavior that I care about. Additionally, there are some specific functionality interfaces, IFunctionalityA and IFunctionalityB, that provide some specialized algorithms. Also, I have some actor, Actor, that performs some operation on IBase objects. Finally, I want to wrap an IBase in a class that keeps the same interface implementations. Is there a good pattern/code structure to help me do this?

The Desired Effect

Here's the setup:

interface IBase {}
interface IFunctionalityA : IBase
{
  int DoSomethingA();
}
interface IFunctionalityB : IBase
{
  int DoSomethingB();
}

// This class is the main implementation problem.
class Wrapper
{
  IBase wrapped;
  Wrapper(IBase obj) { wrapped = obj } 
}

class Actor
{
  void Act(IBase obj)
  {
    int result;
    if (obj is IFunctionalityA objA)
      result = objA.DoSomethingA();
    if (obj is IFunctionalityB objB)
      result = objB.DoSomethingB();
  }
}

Then, if you created a wrapper with an IFunctionalityA object,

IFunctionalityA objA;
var wrapper = new Wrapper(objA);

the wrapper would act like it implemented IFunctionalityA

// ACTS LIKE
class Wrapper : IFunctionalityA
{
  IFunctionalityA wrapped;
  int DoSomethingA() => wrapper.DoSomethingA();
}

and similarly

IFunctionalityB objB;
var wrapper = new Wrapper(objB);

would act like it implemented IFunctionalityB

// ACTS LIKE
class Wrapper : IFunctionalityB
{
  IFunctionalityB wrapped;
  int DoSomethingB() => wrapper.DoSomethingB();
}

Obviously the code can't work exactly like this. I'm looking for a pattern that helps me achieve the same effect.

Restrictions

  1. I can't use generics in the obvious way. I can't just have
    class Wrapper<T> where T : IBase { /*...*/ }
    
    because I just have a collection of IBase objects.
  2. I can't use a property like so
    class Wrapper
    {
      IBase wrapped;
      bool ImplementFunctionalityA => wrapped is IFunctionalityA;
      bool ImplementFunctionalityB => wrapped is IFunctionalityB;
    }
    
    because I'd lose a lot of flexibility that I gain from inheritance in the first place and I have many functionality interfaces.

Possible Solution

I could try to implement a service provider-style design.

interface IBase
{
  T GetFunctionality<T>() where T : IFunctionality;
}
interface IFunctionality { }
interface IFunctionalityA : IFunctionality { int DoSomethingA() { /*...*/ }
interface IFunctionalityB : IFunctionality { int DoSomethingB() { /*...*/ }

class Wrapper : IBase
{
  IBase wrapped;
  T GetFunctionality<T>() where T : IFunctionality
  {
    return wrapped.GetFunctionality<T>();
  }
}

This seems like it would work fine but it seems like it might fragment the connection between the base behavior and specific functionalities. Perhaps that's okay or even better. I'm not sure but any suggestions for patterns, principles, or design would be greatly appreciated. Thanks!

Simple factory VS Factory Method (why use factory method at all)

Im trying to learn patterns and got to Factory, I understand the concept of simple factory and factory method, I know how they work, what I cant understand is what is the benefit of factory method over the simple factory. Example:

//We have our clients here
public class Animal {}
public class Dog extends Animal{}
public class Cat extends Animal{}

In a simple factory we will have this thing:

public Animal getAnimal(String type) {
    switch (type) {
    case "cat": 
      return new Cat;
    case "dog":
      return new Dog;
    }
    return null;
}

Now we go for the factory method:

public abstract class AnimalFactory {
   //Some common animal code here
}
public class DogFactory extends AnimalFactory{
   public Animal getAnimal(){
      //some logic
      return new Dog;
   }
}
public class CatFactory extends AnimalFactory{
   public Animal getAnimal(){
      //some logic
      return new Cat;
   }
}

So here comes the interesting part, for the factory method we will need to use polymorphism but we will still need to instantiate depending on what type we need so I imagine we will have something like this:

public Animal getAnimal(String type) {
    AnimalFactory animalFactory;
    switch (type) {
    case "cat": 
      animalFactory = new CatFactory();  //polymorphism     
      return animalFactory.getAnimal();
    case "dog":
       animalFactory = new DogFactory();  //polymorphism     
      return animalFactory.getAnimal();
    }
    return null;
}

So as far as I know the main idea behing design patterns is to make code more reusable and easier to extend, so imagine we need to add a new animal, say a Parrot. In both cases we create the Parrot class that extends the Animal class and in both cases we will have to go into that switch statement and add a new case "Parrot" For the simple factory we will just instantiate new Parrot directly and for the factory method we will instantiate the ParrotFactory. My question is what is the difference and why do we need the factory method pattern?

The only benefit I can see is that in the factory method you can define common logic for the factories that will extend it (is that it ?)

SQL Server big tables or store data in a xml field

I have a .net solution with a big form with many data that the customer need to fill, like a form with many steps to fill all data we need to get.

So i was wondering if it's better (from a performance and design approach) a traditional big table with many fields, o store the data only on one field of XML type.

Example of one "TraditionalTable":

RecordId CustomerId Data 1 Data 2.... to Data N
1 120 01/01/1980 abcd .... 123
2 20 04/02/2004 fgh .... 230
3 10 05/01/1995 xyz .... 135

Example of one "DataWithXMLField":

RecordId CustomerId FormData
1 120 < data>< customerdetails>< borndate>01/01/1980< /borndate>< /customerdetails >< financialinfo >...."

Use a single docker-compose.yml file with both Docker Compose and Stack, pro and cons?

I'm new of Docker, I'm exploring Docker Compose for development, and Docker Stack over Swarm for production.

I'm facing with issues comparing both capabilities, specifically with regard to use of Secrets, that are not supported without Swarm, and this implies a difference on how env variables are declared. This leads me to a question:

What are pro and cons of use a same docker-compose.yml file shared between Compose and Stack, and what are best patterns?

What I see in pro is that I can maintain a single file, that otherwise probably would share a lot of configuration with a "twin" docker-stack.yml.

What I see in cons is that instead the two files have specific different features, and aside of similarities, their scopes are fundamentally different. Even more if in future I will use a different orchestrating system, where probably a stack file will be totally replaced.

Is recommended to keep these file separated, or is acceptable to unify into a single with specific techniques?

Swift, UIKit. Looking for Coordinator pattern tutorial, NO storyboard

I have searched practically everywhere for some tutorials on Coordinator Pattern with no storyboard.

Maybe someone can share his code from Github so I can have look?

Is anyone able to recommend something? Tutorial, a book to buy, anything. Thanks!