def edit(group_id, ec2=None, rds=None):
    security_groups = ec2.get_all_security_groups(group_ids=[group_id])

    if len(security_groups) == 0:
        return "Missing security groups"

    security_group = security_groups[0]

    for rule in security_group.rules:
        grants_with_cidrs = []

        for grant in rule.grants:
            if grant.cidr_ip:
                ttl = rds.get(GRANT_KEY_FORMULA.format(security_group_id=group_id, protocol=rule.ip_protocol, from_port=rule.from_port, to_port=rule.to_port, cidr=grant.cidr_ip))

                if ttl is None or ttl == 0:
                    grant.time_left = ttl
                else:
                    grant.time_left = int(float(ttl) - time.time())

                grants_with_cidrs.append(grant)

        rule.grants = grants_with_cidrs
    
    if 'X-Forwarded-For' in request.headers:
        ip = request.headers['X-Forwarded-For']
    else:
        ip = request.remote_addr

    return render_template('edit.html', ip=ip, security_group=security_group)
def authorize(ec2=None, rds=None):
    security_group_id, protocol, cidr, from_port, to_port, duration = request.form['security_group_id'], request.form['protocol'], request.form['cidr'], int(request.form['from_port']), int(request.form['to_port']), int(request.form['duration'])

    cidr_fixed = fix_cidr(cidr)

    security_groups = ec2.get_all_security_groups(group_ids=[security_group_id])

    if len(security_groups) == 0:
        return "Security group not found"

    security_group = security_groups[0]

    if security_group.authorize(ip_protocol=protocol, from_port=from_port, to_port=to_port, cidr_ip=cidr_fixed):
        grant_key = GRANT_KEY_FORMULA.format(security_group_id=security_group_id, protocol=protocol, from_port=from_port, to_port=to_port, cidr=cidr_fixed)
        rds.set(grant_key, str(time.time() + duration))
        return redirect("/edit/" + security_group_id)
    else:
        return "An error occurred"
def persist(ec2=None, rds=None):
    security_group_id, protocol, cidr, from_port, to_port = request.args.get('security_group_id'), request.args.get('protocol'), request.args.get('cidr'), int(request.args.get('from_port')), int(request.args.get('to_port'))

    grant_key = GRANT_KEY_FORMULA.format(security_group_id=security_group_id, protocol=protocol, from_port=from_port, to_port=to_port, cidr=cidr)
    rds.delete(grant_key)
    return redirect("/edit/" + security_group_id)
parser.add_argument('--dry', dest='dry', action='store_true', help='Dry run: don\'t actually remove security group rules that have expired')
args = parser.parse_args()

if __name__ == "__main__":
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    logger.addHandler(logging.StreamHandler())
    security_groups = ec2.get_all_security_groups()

    for security_group in security_groups:
        for rule in security_group.rules:
            grants_with_cidrs = []

            for grant in rule.grants:
                if grant.cidr_ip:
                    ttl = rds.get(GRANT_KEY_FORMULA.format(security_group_id=security_group.id, protocol=rule.ip_protocol, from_port=rule.from_port, to_port=rule.to_port, cidr=grant.cidr_ip))

                    if ttl is None or ttl == 0:
                        grant.time_left = ttl
                    else:
                        grant.time_left = int(float(ttl) - time.time())

                    if grant.time_left < 0 and ttl > 0:
                        logging.getLogger("grantaccess").info("Revoking %s: %s %s-%s to %s", security_group.id, rule.ip_protocol, rule.from_port, rule.to_port, grant.cidr_ip)
                        if args.dry is None or args.dry is not True:
                            _revoke(rds, security_group, rule.ip_protocol, rule.from_port, rule.to_port, grant.cidr_ip)
                    else:
                        logging.getLogger("grantaccess").info("No need to revoke %s: %s %s-%s to %s", security_group.id, rule.ip_protocol, rule.from_port, rule.to_port, grant.cidr_ip)

                    grants_with_cidrs.append(grant)