Merge "Add a job to check IRC channel access"
This commit is contained in:
commit
ac849407fa
45
modules/openstack_project/files/irc/channels.yaml
Normal file
45
modules/openstack_project/files/irc/channels.yaml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Copyright 2014 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Global definitions
|
||||||
|
# First set up the access levels (map names in this file to chanserv flags):
|
||||||
|
access:
|
||||||
|
masters: +AFRfiorstv
|
||||||
|
operators: +Aiortv
|
||||||
|
topics: +t
|
||||||
|
|
||||||
|
# Define access that should apply to all channels:
|
||||||
|
global:
|
||||||
|
masters:
|
||||||
|
- openstackinfra
|
||||||
|
operators:
|
||||||
|
- jeblair
|
||||||
|
- mtaylor
|
||||||
|
- clarkb
|
||||||
|
- fungi
|
||||||
|
- SergeyLukjanov
|
||||||
|
- ttx
|
||||||
|
- reed
|
||||||
|
topics:
|
||||||
|
- openstackstatus
|
||||||
|
|
||||||
|
# Individual channel configuration:
|
||||||
|
channels:
|
||||||
|
- name: openstack-infra
|
||||||
|
- name: openstack-meeting
|
||||||
|
topics:
|
||||||
|
- open_stack
|
||||||
|
- name: openstack-nova
|
||||||
|
operators:
|
||||||
|
- russellb
|
144
modules/openstack_project/files/irc/checkaccess.py
Normal file
144
modules/openstack_project/files/irc/checkaccess.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
|
||||||
|
# Copyright 2011, 2013-2014 OpenStack Foundation
|
||||||
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import irc.client
|
||||||
|
import logging
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import sys
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckAccess(irc.client.SimpleIRCClient):
|
||||||
|
log = logging.getLogger("checkaccess")
|
||||||
|
|
||||||
|
def __init__(self, channels, nick, flags):
|
||||||
|
irc.client.SimpleIRCClient.__init__(self)
|
||||||
|
self.identify_msg_cap = False
|
||||||
|
self.channels = channels
|
||||||
|
self.nick = nick
|
||||||
|
self.flags = flags
|
||||||
|
self.current_channel = None
|
||||||
|
self.current_list = []
|
||||||
|
self.failed = True
|
||||||
|
|
||||||
|
def on_disconnect(self, connection, event):
|
||||||
|
if self.failed:
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def on_welcome(self, c, e):
|
||||||
|
self.identify_msg_cap = False
|
||||||
|
self.log.debug("Requesting identify-msg capability")
|
||||||
|
c.cap('REQ', 'identify-msg')
|
||||||
|
c.cap('END')
|
||||||
|
|
||||||
|
def on_cap(self, c, e):
|
||||||
|
self.log.debug("Received cap response %s" % repr(e.arguments))
|
||||||
|
if e.arguments[0] == 'ACK' and 'identify-msg' in e.arguments[1]:
|
||||||
|
self.log.debug("identify-msg cap acked")
|
||||||
|
self.identify_msg_cap = True
|
||||||
|
self.advance()
|
||||||
|
|
||||||
|
def on_privnotice(self, c, e):
|
||||||
|
if not self.identify_msg_cap:
|
||||||
|
self.log.debug("Ignoring message because identify-msg "
|
||||||
|
"cap not enabled")
|
||||||
|
return
|
||||||
|
nick = e.source.split('!')[0]
|
||||||
|
auth = e.arguments[0][0]
|
||||||
|
msg = e.arguments[0][1:]
|
||||||
|
if auth != '+' or nick != 'ChanServ':
|
||||||
|
self.log.debug("Ignoring message from unauthenticated "
|
||||||
|
"user %s" % nick)
|
||||||
|
return
|
||||||
|
self.failed = False
|
||||||
|
self.advance(msg)
|
||||||
|
|
||||||
|
def advance(self, msg=None):
|
||||||
|
if not self.current_channel:
|
||||||
|
if not self.channels:
|
||||||
|
self.connection.quit()
|
||||||
|
return
|
||||||
|
self.current_channel = self.channels.pop()
|
||||||
|
self.current_list = []
|
||||||
|
self.connection.privmsg('chanserv', 'access list %s' %
|
||||||
|
self.current_channel)
|
||||||
|
return
|
||||||
|
if msg.startswith('End of'):
|
||||||
|
found = False
|
||||||
|
for nick, flags, msg in self.current_list:
|
||||||
|
if nick == self.nick and flags == self.flags:
|
||||||
|
self.log.info('%s access ok on %s' %
|
||||||
|
(self.nick, self.current_channel))
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
self.failed = True
|
||||||
|
print ("%s does not have permissions on %s:" %
|
||||||
|
(self.nick, self.current_channel))
|
||||||
|
for nick, flags, msg in self.current_list:
|
||||||
|
print msg
|
||||||
|
print
|
||||||
|
self.current_channel = None
|
||||||
|
self.advance()
|
||||||
|
return
|
||||||
|
parts = msg.split()
|
||||||
|
self.current_list.append((parts[1], parts[2], msg))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='IRC channel access check')
|
||||||
|
parser.add_argument('-l', dest='config',
|
||||||
|
default='/etc/irc/channels.yaml',
|
||||||
|
help='path to the config file')
|
||||||
|
parser.add_argument('-s', dest='server',
|
||||||
|
default='chat.freenode.net',
|
||||||
|
help='IRC server')
|
||||||
|
parser.add_argument('-p', dest='port',
|
||||||
|
default=6667,
|
||||||
|
help='IRC port')
|
||||||
|
parser.add_argument('nick',
|
||||||
|
help='the nick for which access should be validated')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
config = yaml.load(open(args.config))
|
||||||
|
channels = []
|
||||||
|
for channel in config['channels']:
|
||||||
|
channels.append('#' + channel['name'])
|
||||||
|
|
||||||
|
access_level = None
|
||||||
|
for level, names in config['global'].items():
|
||||||
|
if args.nick in names:
|
||||||
|
access_level = level
|
||||||
|
if access_level is None:
|
||||||
|
raise Exception("Unable to determine global access level for %s" %
|
||||||
|
args.nick)
|
||||||
|
flags = config['access'][access_level]
|
||||||
|
|
||||||
|
a = CheckAccess(channels, args.nick, flags)
|
||||||
|
mynick = ''.join(random.choice(string.ascii_uppercase)
|
||||||
|
for x in range(16))
|
||||||
|
a.connect(args.server, int(args.port), mynick)
|
||||||
|
a.start()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -11,6 +11,21 @@
|
|||||||
- console-log
|
- console-log
|
||||||
|
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: gate-config-irc-access
|
||||||
|
node: bare-precise
|
||||||
|
|
||||||
|
builders:
|
||||||
|
- gerrit-git-prep
|
||||||
|
- tox:
|
||||||
|
envlist: 'irc'
|
||||||
|
github-org: 'openstack-infra'
|
||||||
|
project: 'config'
|
||||||
|
|
||||||
|
publishers:
|
||||||
|
- console-log
|
||||||
|
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: gate-config-layout
|
name: gate-config-layout
|
||||||
node: bare-precise
|
node: bare-precise
|
||||||
|
@ -415,6 +415,10 @@ jobs:
|
|||||||
voting: false
|
voting: false
|
||||||
failure-message: Jenkins XML output has changed.
|
failure-message: Jenkins XML output has changed.
|
||||||
success-message: Jenkins XML output is unchanged.
|
success-message: Jenkins XML output is unchanged.
|
||||||
|
- name: gate-config-irc-access
|
||||||
|
voting: false
|
||||||
|
files:
|
||||||
|
- 'modules/openstack_project/files/irc/channels.yaml'
|
||||||
# Continous publishing from master of the following documentation targets:
|
# Continous publishing from master of the following documentation targets:
|
||||||
- name: openstack-admin-guide-cloud
|
- name: openstack-admin-guide-cloud
|
||||||
branch: master
|
branch: master
|
||||||
@ -2528,6 +2532,7 @@ projects:
|
|||||||
- gate-config-pep8
|
- gate-config-pep8
|
||||||
- gate-config-puppet-lint
|
- gate-config-puppet-lint
|
||||||
- gate-config-puppet-syntax
|
- gate-config-puppet-syntax
|
||||||
|
- gate-config-irc-access
|
||||||
- gate-ci-docs
|
- gate-ci-docs
|
||||||
- check-projects-yaml-alphabetized
|
- check-projects-yaml-alphabetized
|
||||||
gate:
|
gate:
|
||||||
@ -2535,6 +2540,7 @@ projects:
|
|||||||
- gate-config-pep8
|
- gate-config-pep8
|
||||||
- gate-config-puppet-lint
|
- gate-config-puppet-lint
|
||||||
- gate-config-puppet-syntax
|
- gate-config-puppet-syntax
|
||||||
|
- gate-config-irc-access
|
||||||
- check-projects-yaml-alphabetized
|
- check-projects-yaml-alphabetized
|
||||||
post:
|
post:
|
||||||
- ci-docs
|
- ci-docs
|
||||||
|
5
tox.ini
5
tox.ini
@ -14,6 +14,11 @@ commands = flake8
|
|||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
||||||
|
[testenv:irc]
|
||||||
|
deps = PyYAML
|
||||||
|
irc
|
||||||
|
commands = python modules/openstack_project/files/irc/checkaccess.py -l modules/openstack_project/files/irc/channels.yaml openstackinfra
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
show-source = True
|
show-source = True
|
||||||
exclude = .tox
|
exclude = .tox
|
||||||
|
Loading…
Reference in New Issue
Block a user