Is it possible to automate Cloudwatch Billing Alarms - python

when a new AWS Account gets created or migrated into our environment the details get put into a DynamoDB, below is an example of the details of stored in the DDB:
{'Count': 57,
'Items': [{'AccountId': 'Account Number Here',
'AccountName': 'Account Name Here',
'Arn': 'arn:here',
'Email': 'email#somecompany.com',
'MainAccount': 'The Main Billing Account',
'Type': 'prod'},
}
I'm wondering if there is some way, I can possibly scan the DDB then when a new entry is added create a CloudWatch billing alarm using my code below, I understand this will need modifying and I'll admit this is very manual and not very automated, which is why I'm enquiring here:
import boto3
my_profile = input(
"Please input the profile name you will use stored in ~\.aws\config: \n"
)
sess = boto3.Session(profile_name=my_profile, region_name="us-east-1")
# US-East-1 as that is where Billing Alarms are handled.
sns_name = input("Enter SNS Topic name with no spaces, you can use underscores: \n")
sns_client = sess.client("sns")
# Creates SNS Topic
result = sns_client.create_topic(Name=sns_name)
for value in result.values():
print(value)
topic_arn = input(
"Copy & Paste Topic ARN from printed result above including arn: : \n"
)
print("Topic Created..")
subscribe_endpoint = input("Enter an email address for the subscription: \n")
print("Subscription created, check your emails and confirm the subscription.")
# Creates Subscription & Sets up email protocol for that particular topic, ammend Topic Arn from previous SNS topic and change enpoint to respective email address.
sns_client.subscribe(
TopicArn=topic_arn, # Grab ARN from list_topics API call.
Protocol="email",
Endpoint=subscribe_endpoint, # Input email address here
ReturnSubscriptionArn=True,
)
cw = sess.client("cloudwatch")
alarm_name = input("Enter an alarm name: \n")
alarm_desc = input("Enter an alarm description: \n")
alarm_threshold = int(input("Enter the alarm threshold in integer values: \n"))
if alarm_threshold == "":
print("please enter integer values only")
exit()
metrics_id = input("Please enter a metric ID,: \n")
linked_account_id = input(
"Please type the account ID in reference to your billing alarm, please note it can take 24hrs for this to appear if recently migrated: \n"
)
# Below creates the alarm, change Name, Description, Threshold and LinkedAccount & Label
cw.put_metric_alarm(
AlarmName=alarm_name,
ActionsEnabled=True,
MetricName="EstimatedCharges",
Namespace="AWS/Billing",
Statistic="Maximum",
Dimensions=[
{"Name": "Currency", "Value": "USD"},
{"Name": "LinkedAccount", "Value": linked_account_id},
],
Period=21600,
AlarmDescription=alarm_desc,
AlarmActions=[topic_arn],
EvaluationPeriods=1,
DatapointsToAlarm=1,
Threshold=alarm_threshold,
ComparisonOperator="GreaterThanOrEqualToThreshold",
TreatMissingData="missing",
)
print("\n")
print(
f"Alarm: {alarm_name} has been created, actioning on topic {topic_arn}. The threshold is {alarm_threshold} to linked account {linked_account_id}, an Email will be sent to {subscribe_endpoint} if this threshold is breached/exceeded."
)
I appreciate the code relies on User Input, however if there is some way to generalize or grab some information from the DDB and use it similar to below:
sns_name = #This can relate to the account name Maybe "AccName_SNS_Topic"
topic_arn = "the topic arn" #I'm fairly new to Python
# so I'm not sure how to pull the exact topic arn from it once it's created and stored
# in the variable.
subscribe_endpoint = "The email address linked to the account in DDB"
alarm_name = "AccountName - Dev or Prod (Stored in type on DDB) - Billing Alarm"
alarm_desc = "As above"
alarm_threshold = 700
# We can skip metrics ID, I don't think we actually need it
linked_account_id = "Account Number stored in AccountId in DDB"
The end goal is to be able to get this into a lambda with an event bridge or something similar. Please note some accounts already have billing alarms set so it would only be for new accounts only. I appreciate any advice or input you may be able to assist me with, Thanks in advance.

Related

Unable to set “User cannot change password“ ACE with python ldap3

I am trying to create a service account via the Ldap3 library in Python. The service account is successfully created, but there is a small problem. The "User cannot change password" checkboxes is not selected.
I did some research and found that to set this property I need to follow some steps given here : https://learn.microsoft.com/en-us/windows/win32/adsi/modifying-user-cannot-change - password-ldap-provider . The logic given in this link is in a different programming language than Python, so i tried to replicate the same logic in Python. From what we understand, I’ve implemented the feature, which executed successfully, but didn't see the expected effect on the AD server ("User cannot change password" checkbox is still unchecked).
Below is the code used to create and add the ACL object to the service account.
def create_object_ace(privguid, sid):
print("creating ace object")
nace = ldaptypes.ACE()
nace['AceType'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_DENIED_OBJECT_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CONTROL_ACCESS
acedata['ObjectType'] = string_to_bin(privguid)
acedata['InheritedObjectType'] = b''
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
assert sid == acedata['Sid'].formatCanonical()
acedata['Flags'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT
nace['Ace'] = acedata
return nace
s = Server('ad_server.com', get_info=ALL)
c = Connection(s, user="testdomain\\username", password="password", authentication=NTLM)
c.search(search_base="DC=testad,DC=com", search_filter="(CN=svc_account_47)",
search_scope=SUBTREE, attributes=['objectSid', 'sAMAccountName'])
entry = c.entries[0]
usersid = entry['objectSid'].value
controls = security_descriptor_control(sdflags=0x04)
c.search(search_base="DC=testahs,DC=com", search_filter='(&(objectCategory=domain))',
attributes=['SAMAccountName', 'nTSecurityDescriptor'], controls=controls)
entry = c.entries[0]
secDescData =. entry['nTSecurityDescriptor'].raw_values[0]
secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR(data=secDescData)
secDesc['Dacl']['Data'].append(create_object_ace('ab721a53-1e2f-11d0-9819-00aa0040529b', usersid)) # This GUID is for 'User cannot change password'
dn = entry.entry_dn
data = secDesc.getData()
c.modify(dn, {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [data])}, controls=controls)
print(c.result)
# gives -> {'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'modifyResponse'}
The Python code reference is from the following link:
https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/ntlmrelayx/attacks/ldapattack.py
Can someone help me here. Thanks in advance.

Way to store user input data to be called later in Python?

New to Python and am working on a task my friend gave me. The objective for this portion is to find user information that was previously added to a dictionary. I am trying to find a way that if the user is searching for a particular user, only that user's info will be returned. So far this is the code I have for this portion of the project:
selection = input('Please select an option 1 - 4:\t')
if selection == '1':
print('Add user - Enter the information for the new user:\t')
first_name = input('First name:\t')
last_name = input('Last name:\t')
hair_color = input('Hair color:\t')
eye_color = input('Eye color:\t')
age = input('Age:\t')
user_info = {}
user_info['First name'] = first_name
user_info['Last name'] = last_name
user_info['Hair color'] = hair_color
user_info['Eye color'] = eye_color
user_info['Age'] = age
Skipping code for sake of space on post
if selection == '3':
print('\nChoose how to look up a user')
print('1 - First name')
print('2 - Last name')
print('3 - Hair color')
print('4 - Eye color')
print('5 - Age')
print('6 - Exit to main menu\n')
search_option = input('Enter option:\t')
if search_option == '1' or search_option == 'First name' or search_option == 'first name':
input('Enter the first name of the user you are looking for:\t')
Any and all help is much appreciated!!
Depending on your project, using a dictionary might be difficult in the future. Let's not go down a dark road. Take a moment and assess the situation.
We know that we want to collect some information from the user, such as:
first name
last name
hair color
...etc
We also want to store the User object to retrieve later based on a particular ID. In your code, you search for other users based on attributes, but what if two or more users share the same attribute, for example, first name?
What your asking for are attributes associated with a particular user. Why not create a class called User?
class User:
def __init__(self, id, first_name, last_name, hair_color):
# You can also check if any attributes are blank and throw an exception.
self._id = id
self._first_name = first_name
self._last_name = last_name
self._hair_color = hair_color
# add more attributes if you want
# a getter to access the self._id property
#property
def id(self):
return self._id
def __str__(self):
return f"ID: {self._id} Name: {self._first_name} {self._last_name}
Hair Color: {self._hair_color}"
In your main function, you can now ask for the user details and store them in a class which you can append to a List.
from User import User
def ask_for_input(question):
answer = input(question)
return answer.strip() # strip any user created white space.
def main():
# Store our users
users = []
# Collect the user info
id = ask_for_input(question = "ID ")
first_name = ask_for_input(question = "First Name ")
last_name = ask_for_input(question = "Last Name ")
hair_color= ask_for_input(question = "Hair Color ")
# Create our user object
user = User(id=id, first_name=first_name, last_name=last_name, hair_color=hair_color)
print(user)
# accessing the id property
print(user.id)
users.append(user)
if __name__ == '__main__':
main()
You may also want to improve on the above class, for example, error checking, and adding type hints to make the code more readable.
If you're just storing the user information, a data class might be more appropriate.
If your looking for a broad suggestion, you could use mongob, it makes a great way to store data to be retrieved later, here is an example i built for another question. The prerequisites is that you'd have to get the mongod server running before you can use the pip install:
Here is an example of how to get it going and how easy it easy to retrieve data like yours
pip3 install pymongo
from pymongo import MongoClient
client = MongoClient()
client = MongoClient('localhost', 27017)
db = client.pymongo_test
posts = db.posts
post_data = {
'title': 'The title of this post',
'content': 'pymongo is awesome',
'author': 'Bill'
}
result = posts.insert_one(post_data)
print('One post: {0}'.format(result.inserted_id))
bills_post = posts.find_one({'author': 'Bill'})
print(bills_post)
#One post: 5dc61c0cc2b75ebc458da31f
#{'_id': ObjectId('5dc61bf76071bde943ca262b'), 'title': 'The title of this post', 'content': 'pymongo is awesome', 'author': 'Bill'}

How to select the value to check the account and password?

I want to make a login window , and there are two QlineEdits in this window . We must input the correct account and password in it then login successful.
There are two groups account and password in member.db
First : Account:aaa , Password:000
Second : Account:bbb , Password:111
Here is part of my code: Howerver when I select the data of account , it can't catch the value .
def buttonClicked(self):
model = QSqlQueryModel()
a=model.setQuery("SELECT Password FROM member WHERE Account = values(\'{0}')".format(self.AccountEdit))
if a==self.PasswordEdit.text():
QtGui.QMessageBox.information(self, 'message',"Congratulations !!!")
else:
QtGui.QMessageBox.warning(self, 'message',"Error !!!")
I think the error is in a=model.setQuery("SELECT Password FROM member WHERE Account = values(\'{0}')".format(self.AccountEdit)) this code.
Because I tried to print(a) and it return None .
This is not valid SQL; you should use just WHERE Account = 'name'.
Furthermore, to prevent SQL injection attacks, you should use parameters; this is possible only by using a separate QSqlQuery object:
query = QSqlQuery()
query.prepare("SELECT Password FROM member WHERE Account = ?")
query.bindValue(0, self.AccountEdit)
query.exec_()
model = QSqlQueryModel()
model.setQuery(query)

Add a Contact To Google SystemGroup

I'm developing an app for adding a contact detail to google contacts using gdata and python. I can add a contact to "Other contacts" group but not to My Contact System Group.
here is the coding so far
def CreateMenu(self,nm,tp,em):
new_contact = gdata.contacts.data.ContactEntry(name=gdata.data.Name(full_name=gdata.data.FullName(text=nm)))
new_contact.phone_number.append(gdata.data.PhoneNumber(text=tp, primary='true', rel=gdata.data.WORK_REL))
new_contact.email.append(gdata.data.Email(address=em, rel=gdata.data.WORK_REL))
entry = self.gd_client.CreateContact(new_contact)
if entry:
print 'Creation successful!'
print 'ID for the new contact:', entry.id.text
else:
print 'Upload error.'
I found the solution:
feed = gd_client.GetGroups()
group = filter(lambda g: g.title.text == 'System Group: My Contacts', feed.entry)[0]
gmeminfo = gdata.contacts.data.GroupMembershipInfo(href=group.get_id())
new_contact.group_membership_info.append(gmeminfo)

Retrieve gtalk nickname in python xmpp

In python xmpp module, I'm able to retrieve the nickname of any contacts as follows:
self.connection.auth(userJid.getNode(), self.password)
self.roster = self.connection.getRoster()
name = self.roster.getName(buddyJid)
..where buddyJid is of the form user#gmail.com.
Now, I need to retrieve the nickname of the user who authenticates the connection (userJid). I cannot find the name using the above method.
Which method can I use retrieve the name of the current user?
This information is not in the roster. You will need to query the clients individually and get their vCard by sending this IQ :
<iq from='stpeter#jabber.org/roundabout'
id='v1'
type='get'>
<vCard xmlns='vcard-temp'/>
</iq>
Thank you nicholas_o, this is a sample function I put together based your suggestion. (The XML logic isn't ideal, but it was sufficient for the simple task I needed this for)
def vcard(disp, jid):
msg = xmpp.protocol.Iq()
msg.setType('get')
msg.setTo(jid)
qc = msg.addChild('vCard')
qc.setAttr('xmlns', 'vcard-temp')
rep = disp.SendAndWaitForResponse(msg)
# to see what other fields are available in the XML output:
# print rep
userid=fname=lname=title=department=region=None
for i in rep.getChildren():
for j in i.getChildren():
if j.getName() == "TITLE":
title = j.getData().encode('utf-8')
for k in j.getChildren():
if k.getName() == "GIVEN":
fname = k.getData().encode('utf-8')
if k.getName() == "FAMILY":
lname = k.getData().encode('utf-8')
if k.getName() == "ORGUNIT":
department = k.getData().encode('utf-8')
if k.getName() == "REGION":
region = k.getData().encode('utf-8')
return fname, lname, title, department, region

Categories

Resources