This commit is contained in:
simonmicro 2025-10-29 18:25:34 +01:00 committed by GitHub
commit 6d3f6602f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 595 additions and 847 deletions

View file

@ -21,6 +21,11 @@ jobs:
platforms: all platforms: all
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1.6.0 uses: docker/setup-buildx-action@v1.6.0
- name: Login to DockerHub
uses: docker/login-action@v1.10.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v1.10.0 uses: docker/login-action@v1.10.0
with: with:
@ -34,7 +39,7 @@ jobs:
file: ./docker/docker-py3-kms/Dockerfile file: ./docker/docker-py3-kms/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6
push: true push: true
tags: ghcr.io/py-kms-organization/py-kms:python3 tags: pykmsorg/py-kms:python3,ghcr.io/py-kms-organization/py-kms:python3
build-args: | build-args: |
BUILD_COMMIT=${{ github.sha }} BUILD_COMMIT=${{ github.sha }}
BUILD_BRANCH=${{ github.ref_name }} BUILD_BRANCH=${{ github.ref_name }}
@ -45,7 +50,7 @@ jobs:
file: ./docker/docker-py3-kms-minimal/Dockerfile file: ./docker/docker-py3-kms-minimal/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6
push: true push: true
tags: ghcr.io/py-kms-organization/py-kms:latest,ghcr.io/py-kms-organization/py-kms:minimal tags: pykmsorg/py-kms:latest,ghcr.io/py-kms-organization/py-kms:latest,pykmsorg/py-kms:minimal,ghcr.io/py-kms-organization/py-kms:minimal
build-args: | build-args: |
BUILD_COMMIT=${{ github.sha }} BUILD_COMMIT=${{ github.sha }}
BUILD_BRANCH=${{ github.ref_name }} BUILD_BRANCH=${{ github.ref_name }}

View file

@ -21,6 +21,11 @@ jobs:
platforms: all platforms: all
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1.6.0 uses: docker/setup-buildx-action@v1.6.0
- name: Login to DockerHub
uses: docker/login-action@v1.10.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v1.10.0 uses: docker/login-action@v1.10.0
with: with:
@ -34,7 +39,7 @@ jobs:
file: ./docker/docker-py3-kms/Dockerfile file: ./docker/docker-py3-kms/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6
push: true push: true
tags: ghcr.io/py-kms-organization/py-kms:python3-next tags: pykmsorg/py-kms:python3-next,ghcr.io/py-kms-organization/py-kms:python3-next
build-args: | build-args: |
BUILD_COMMIT=${{ github.sha }} BUILD_COMMIT=${{ github.sha }}
BUILD_BRANCH=${{ github.ref_name }} BUILD_BRANCH=${{ github.ref_name }}
@ -45,7 +50,7 @@ jobs:
file: ./docker/docker-py3-kms-minimal/Dockerfile file: ./docker/docker-py3-kms-minimal/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6
push: true push: true
tags: ghcr.io/py-kms-organization/py-kms:latest-next,ghcr.io/py-kms-organization/py-kms:minimal-next tags: pykmsorg/py-kms:latest-next,ghcr.io/py-kms-organization/py-kms:latest-next,pykmsorg/py-kms:minimal-next,ghcr.io/py-kms-organization/py-kms:minimal-next
build-args: | build-args: |
BUILD_COMMIT=${{ github.sha }} BUILD_COMMIT=${{ github.sha }}
BUILD_BRANCH=${{ github.ref_name }} BUILD_BRANCH=${{ github.ref_name }}

View file

@ -2,6 +2,7 @@
![repo-size](https://img.shields.io/github/repo-size/Py-KMS-Organization/py-kms) ![repo-size](https://img.shields.io/github/repo-size/Py-KMS-Organization/py-kms)
![open-issues](https://img.shields.io/github/issues/Py-KMS-Organization/py-kms) ![open-issues](https://img.shields.io/github/issues/Py-KMS-Organization/py-kms)
![last-commit](https://img.shields.io/github/last-commit/Py-KMS-Organization/py-kms/master) ![last-commit](https://img.shields.io/github/last-commit/Py-KMS-Organization/py-kms/master)
![docker-pulls](https://img.shields.io/docker/pulls/pykmsorg/py-kms)
![read-the-docs](https://img.shields.io/readthedocs/py-kms) ![read-the-docs](https://img.shields.io/readthedocs/py-kms)
*** ***

View file

@ -5,6 +5,9 @@ What follows are some guides how to start the `pykms_Server.py` script, which pr
You can simply manage a daemon that runs as a background process. This can be achieved by using any of the notes below or by writing your own solution. You can simply manage a daemon that runs as a background process. This can be achieved by using any of the notes below or by writing your own solution.
### Docker ### Docker
![docker-pulls](https://img.shields.io/docker/pulls/pykmsorg/py-kms)
![docker-size](https://img.shields.io/docker/image-size/pykmsorg/py-kms)
If you wish to get _py-kms_ just up and running without installing any dependencies or writing own scripts: Just use Docker ! If you wish to get _py-kms_ just up and running without installing any dependencies or writing own scripts: Just use Docker !
Docker also solves problems regarding the explicit IPv4 and IPv6 usage (it just supports both). The following Docker also solves problems regarding the explicit IPv4 and IPv6 usage (it just supports both). The following
command will download, "install" and start _py-kms_ and also keep it alive after any service disruption. command will download, "install" and start _py-kms_ and also keep it alive after any service disruption.

File diff suppressed because it is too large Load diff

View file

@ -184,7 +184,7 @@ def client_update():
if sName == name + 'Enterprise' or \ if sName == name + 'Enterprise' or \
sName == name[:6] + 'ProfessionalPlus' + name[6:]: sName == name[:6] + 'ProfessionalPlus' + name[6:]:
clt_config['KMSClientSkuID'] = skuitem['Id'] clt_config['KMSClientSkuID'] = skuitem['Id']
clt_config['RequiredClientCount'] = int(kmsitem['NCountPolicy']) clt_config['RequiredClientCount'] = int(kmsitem.get('NCountPolicy', 25)) # if not given default to 25
clt_config['KMSProtocolMajorVersion'] = int(float(kmsitem['DefaultKmsProtocol'])) clt_config['KMSProtocolMajorVersion'] = int(float(kmsitem['DefaultKmsProtocol']))
clt_config['KMSProtocolMinorVersion'] = 0 clt_config['KMSProtocolMinorVersion'] = 0
clt_config['KMSClientLicenseStatus'] = 2 clt_config['KMSClientLicenseStatus'] = 2

View file

@ -20,7 +20,7 @@ def epidGenerator(kmsId, version, lcid):
for csvlkitem in csvlkitems: for csvlkitem in csvlkitems:
try: try:
if kmsId in [ uuid.UUID(kmsitem) for kmsitem in csvlkitem['Activate'] ]: if kmsId in [ uuid.UUID(kmsitem) for kmsitem in csvlkitem['Activate'] ]:
pkeys.append( (csvlkitem['GroupId'], csvlkitem['MinKeyId'], csvlkitem['MaxKeyId'], csvlkitem['InvalidWinBuild']) ) pkeys.append( (csvlkitem['GroupId'], csvlkitem['MinKeyId'], csvlkitem['MaxKeyId'], csvlkitem.get('InvalidWinBuild', '[]')) )
else: else:
# fallback to Windows Server 2019 parameters. # fallback to Windows Server 2019 parameters.
pkeys.append( ('206', '551000000', '570999999', '[0,1,2]') ) pkeys.append( ('206', '551000000', '570999999', '[0,1,2]') )
@ -40,10 +40,11 @@ def epidGenerator(kmsId, version, lcid):
hosts.append(winbuild) hosts.append(winbuild)
except KeyError: except KeyError:
# fallback to Windows Server 2019 parameters. # fallback to Windows Server 2019 parameters.
hosts.append( {'BuildNumber':'17763', 'PlatformId':'3612', 'MinDate':'02/10/2018'} ) hosts.append( {'BuildNumber':'17763', 'PlatformId':'3612', 'ReleaseDate':'2018-10-02T00:00:00Z'} )
host = random.choice(hosts) host = random.choice(hosts)
BuildNumber, PlatformId, MinDate = host['BuildNumber'], host['PlatformId'], host['MinDate']
BuildNumber, PlatformId, ReleaseDate = host['BuildNumber'], host['PlatformId'], host['ReleaseDate'].rstrip("Z")
# Generate Part 3 and Part 4: Product Key ID # Generate Part 3 and Part 4: Product Key ID
productKeyID = random.randint(MinKeyId, MaxKeyId) productKeyID = random.randint(MinKeyId, MaxKeyId)
@ -55,11 +56,11 @@ def epidGenerator(kmsId, version, lcid):
languageCode = lcid # (C# CultureInfo.InstalledUICulture.LCID) languageCode = lcid # (C# CultureInfo.InstalledUICulture.LCID)
# Generate Part 8: KMS Host Activation Date # Generate Part 8: KMS Host Activation Date
d = datetime.datetime.strptime(MinDate, "%d/%m/%Y") d = datetime.datetime.fromisoformat(ReleaseDate)
minTime = datetime.date(d.year, d.month, d.day) minTime = datetime.date(d.year, d.month, d.day)
# Generate Year and Day Number # Generate Year and Day Number
randomDate = datetime.date.fromtimestamp(random.randint(time.mktime(minTime.timetuple()), time.mktime(datetime.datetime.now().timetuple()))) randomDate = datetime.date.fromtimestamp(random.randint(int(time.mktime(minTime.timetuple())), int(time.mktime(datetime.datetime.now().timetuple()))))
firstOfYear = datetime.date(randomDate.year, 1, 1) firstOfYear = datetime.date(randomDate.year, 1, 1)
randomDayNumber = int((time.mktime(randomDate.timetuple()) - time.mktime(firstOfYear.timetuple())) / 86400 + 0.5) randomDayNumber = int((time.mktime(randomDate.timetuple()) - time.mktime(firstOfYear.timetuple())) / 86400 + 0.5)

View file

@ -15,33 +15,34 @@ def _get_serve_count():
return _serve_count return _serve_count
_kms_items = None _kms_items = None
_kms_items_ignored = None _kms_items_noglvk = None
def _get_kms_items_cache(): def _get_kms_items_cache():
global _kms_items, _kms_items_ignored global _kms_items, _kms_items_noglvk
if _kms_items is None: if _kms_items is None:
_kms_items = {} _kms_items = {} # {group: str -> {product: str -> gvlk: str}}
_kms_items_ignored = 0 _kms_items_noglvk = 0
queue = [kmsDB2Dict()] for section in kmsDB2Dict():
while len(queue): for element in section:
item = queue.pop(0) if "KmsItems" in element:
if isinstance(item, list): for product in element["KmsItems"]:
for i in item: group_name = product["DisplayName"]
queue.append(i) items = {}
elif isinstance(item, dict): for item in product["SkuItems"]:
if 'KmsItems' in item: items[item["DisplayName"]] = item["Gvlk"]
queue.append(item['KmsItems']) if not item["Gvlk"]:
elif 'SkuItems' in item: _kms_items_noglvk += 1
queue.append(item['SkuItems']) if len(items) == 0:
elif 'Gvlk' in item: continue
if len(item['Gvlk']): if group_name not in _kms_items:
_kms_items[item['DisplayName']] = item['Gvlk'] _kms_items[group_name] = {}
else: _kms_items[group_name].update(items)
_kms_items_ignored += 1 elif "DisplayName" in element and "BuildNumber" in element and "PlatformId" in element:
#else: pass # these are WinBuilds
# print(item) elif "DisplayName" in element and "Activate" in element:
else: pass # these are CsvlkItems
raise NotImplementedError(f'Unknown type: {type(item)}') else:
return _kms_items, _kms_items_ignored raise NotImplementedError(f'Unknown element: {element}')
return _kms_items, _kms_items_noglvk
app = Flask('pykms_webui') app = Flask('pykms_webui')
app.jinja_env.globals['start_time'] = datetime.datetime.now() app.jinja_env.globals['start_time'] = datetime.datetime.now()
@ -90,7 +91,7 @@ def root():
count_clients=countClients, count_clients=countClients,
count_clients_windows=countClientsWindows, count_clients_windows=countClientsWindows,
count_clients_office=countClientsOffice, count_clients_office=countClientsOffice,
count_projects=len(_get_kms_items_cache()[0]) count_projects=sum([len(entries) for entries in _get_kms_items_cache()[0].values()])
), 200 if error is None else 500 ), 200 if error is None else 500
@app.route('/readyz') @app.route('/readyz')
@ -125,15 +126,15 @@ def license():
@app.route('/products') @app.route('/products')
def products(): def products():
_increase_serve_count() _increase_serve_count()
items, ignored = _get_kms_items_cache() items, noglvk = _get_kms_items_cache()
countProducts = len(items) countProducts = sum([len(entries) for entries in items.values()])
countProductsWindows = len([i for i in items if 'windows' in i.lower()]) countProductsWindows = sum([len(entries) for (name, entries) in items.items() if 'windows' in name.lower()])
countProductsOffice = len([i for i in items if 'office' in i.lower()]) countProductsOffice = sum([len(entries) for (name, entries) in items.items() if 'office' in name.lower()])
return render_template( return render_template(
'products.html', 'products.html',
path='/products/', path='/products/',
products=items, products=items,
filtered=ignored, filtered=noglvk,
count_products=countProducts, count_products=countProducts,
count_products_windows=countProductsWindows, count_products_windows=countProductsWindows,
count_products_office=countProductsOffice count_products_office=countProductsOffice

View file

@ -32,22 +32,36 @@
<hr> <hr>
<style scoped>
td.glvk {
width: 24rem;
}
pre.glvk {
width: min-content;
}
</style>
{% for group_name, group_products in products | dictsort %}
<h1 class="title">{{ group_name }}</h1>
<table class="table is-bordered is-striped is-hoverable is-fullwidth"> <table class="table is-bordered is-striped is-hoverable is-fullwidth">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th><abbr title="Group Volume License Key">GVLK</abbr></th> <th class="glvk"><abbr title="Group Volume License Key">GVLK</abbr></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for name, gvlk in products | dictsort %} {% for name, gvlk in group_products | dictsort %}
{% if gvlk %} <tr>
<tr> <td>{{ name }}</td>
<td>{{ name }}</td> <td class="glvk">
<td><pre>{{ gvlk }}</pre></td> {% if gvlk %}
</tr> <pre class="glvk">{{ gvlk }}</pre>{% endif %}
{% endif %} </td>
{% endfor %} </tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
{% endblock %} {% endfor %}
{% endblock %}